我将如何使用 Kotlin 的序列化库对对象列表进行反序列化?
How would I go about de-serializing a list of objects using Kotlin's serialization library?
我在 运行 时 运行 遇到以下异常,调试器试图为我的 Kotlin Android 食谱应用程序从我的 Algolia 索引中反序列化数据 I我正在尝试使用 Kotlinx.Serialization 库创建。应用程序编译并且 运行 没问题,但 UI.
上没有显示结果
kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset -1: Failed to parse 'int'.
JSON input: {"amount":1.5,"name":"green beans","original":"1.5 pounds of green beans","unit":"pounds","unitLong":"pounds","unitShort":"lbs"}
现在从这个异常的外观来看,反序列化器似乎正在尝试反序列化我的 Ingredients 数据 class。我将如何反序列化它?
正在发送的示例 JSON 数据。
{
"cuisine": "European",
"diet": "Vegetarian",
"difficulty": 2,
"dishType": "Dinner",
"duration": 30,
"durationUnit": "minutes",
"image": "https://c.recipeland.com/images/r/1396/12f9fc271d8f1bfac5f6_550.jpg",
"ingredients": [
{
"amount": 1.5,
"name": "green beans",
"original": "1.5 pounds of green beans",
"unit": "pounds",
"unitLong": "pounds",
"unitShort": "lbs"
},
{
"amount": 1,
"name": "onion",
"original": "1.5 medium onion",
"unit": "medium",
"unitLong": "medium",
"unitShort": "med"
},
{
"amount": 2,
"name": "garlic",
"original": "2 teaspoons of garlic",
"unit": "teaspoons",
"unitLong": "teaspoons",
"unitShort": "tsps"
},
{
"amount": 1,
"name": "olive oil",
"original": "1 teaspoon olive oil",
"unit": "teaspoon",
"unitLong": "teaspoon",
"unitShort": "tsps"
},
{
"amount": 1,
"name": "mushrooms",
"original": "1 cup mushrooms",
"unit": "cup",
"unitLong": "cup",
"unitShort": "cup"
},
{
"amount": 1,
"name": "cherry tomatoes",
"original": "1 cup cherry tomatoes",
"unit": "cup",
"unitLong": "cup",
"unitShort": "cup"
}
],
"name": "Green Beans with Mushrooms and Cherry Tomatoes",
"preparation": [
"Steam green beans until tender.",
"Drain and set aside. Sauté onion and garlic in a medium skillet coated with olive oil, until tender. About 2 to 3 minutes.",
"Add mushrooms and sauté until tender. Stir in green beans and tomotoes until heated."
],
"yield": 4,
"objectID": "0"
}
我的食谱数据 classes 设置如下:
Recipe.kt
@IgnoreExtraProperties
@Serializable
data class Recipe(
var difficulty: Int = 0,
var dishType: String? = null,
var duration: Int = 0,
var durationUnit: String? = null,
var image: String? = null,
var diet: String? = null,
var cuisine: String? = null,
var name: String? = null,
var ingredients: List<Ingredient> = emptyList(),
var preparation: List<String> = emptyList(),
var yield: Int = 0
) {
Ingredient.kt
@Serializable
data class Ingredient(
var amount: Int = 0,
var name: String? = null,
var original: String? = null, // Original text of the ingredient
var unit: String? = null,
var unitLong: String? = null,
var unitShort: String? = null
)
我从 Algolia 的 InstantSearch 入门指南Android 中获得的这段代码对索引中的数据进行了反序列化。
private val datasourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
hit.deserialize(Recipe.serializer()) // Problem line I assume
}
val pagedListConfig = PagedList.Config.Builder().setPageSize(50).build()
val recipes: LiveData<PagedList<Recipe>> =
LivePagedListBuilder(datasourceFactory, pagedListConfig).build()
val searchBox =
SearchBoxConnectorPagedList(searcher, listOf(recipes))
我尝试使用以下代码手动创建对象,但我 运行 在尝试创建成分列表时遇到问题。
val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
Recipe(
hit.json.getPrimitive("difficulty").content.toInt(),
hit.json.getPrimitive("dishType").content,
hit.json.getPrimitive("duration").content.toInt(),
hit.json.getPrimitive("durationUnit").content,
hit.json.getPrimitive("image").content,
hit.json.getPrimitive("diet").content,
hit.json.getPrimitive("cuisine").content,
hit.json.getPrimitive("name").content,
listOf(
Ingredient(
hit.json.getPrimitive("amount").content.toInt(),
hit.json.getPrimitive("name").content,
hit.json.getPrimitive("original").content,
hit.json.getPrimitive("unit").content,
hit.json.getPrimitive("unitLong").content,
hit.json.getPrimitive("unitShort").content
)
),
hit.json.getArray("preparation").content.map { prep -> prep.content },
hit.json.getPrimitive("yield").content.toInt()
)
}
我不是 100% 确定我是否正确地创建了 preparation 属性 成员以及整个创建成分列表的过程有副作用跟踪我。任何帮助将不胜感激,对于我的第一个 post 很长,我深表歉意。我已经为此做了几天,但我对下一步该做什么感到困惑。
正如您看到的这一行:
kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset -1: Failed to parse 'int'.
这里发生了 JsonDecodingException 异常,这就是它没有给出正确响应的原因。您必须检查所有数据 classes 是否与 JSON Object.
中的变量相同
我发现你的数据有 1 个问题 class,首先检查这个 JSON 回复:
"amount": 1.5
现在检查您的数据 class,其中有 var amount: Int = 0
@Serializable
data class Ingredient(
var amount: Int = 0,
var name: String? = null,
var original: String? = null, // Original text of the ingredient
var unit: String? = null,
var unitLong: String? = null,
var unitShort: String? = null
)
此处JSON 对象在Float
中,而您正在将其存储在Int
中,这可能会导致异常。确保数据 class 中的所有值都正确。
或者为了变通,您只需将数据中的字符串设为所有变量 class 以检查所有响应是否正确显示,然后根据您的要求将它们转换为 Int、Float。
我在 运行 时 运行 遇到以下异常,调试器试图为我的 Kotlin Android 食谱应用程序从我的 Algolia 索引中反序列化数据 I我正在尝试使用 Kotlinx.Serialization 库创建。应用程序编译并且 运行 没问题,但 UI.
上没有显示结果kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset -1: Failed to parse 'int'.
JSON input: {"amount":1.5,"name":"green beans","original":"1.5 pounds of green beans","unit":"pounds","unitLong":"pounds","unitShort":"lbs"}
现在从这个异常的外观来看,反序列化器似乎正在尝试反序列化我的 Ingredients 数据 class。我将如何反序列化它?
正在发送的示例 JSON 数据。
{
"cuisine": "European",
"diet": "Vegetarian",
"difficulty": 2,
"dishType": "Dinner",
"duration": 30,
"durationUnit": "minutes",
"image": "https://c.recipeland.com/images/r/1396/12f9fc271d8f1bfac5f6_550.jpg",
"ingredients": [
{
"amount": 1.5,
"name": "green beans",
"original": "1.5 pounds of green beans",
"unit": "pounds",
"unitLong": "pounds",
"unitShort": "lbs"
},
{
"amount": 1,
"name": "onion",
"original": "1.5 medium onion",
"unit": "medium",
"unitLong": "medium",
"unitShort": "med"
},
{
"amount": 2,
"name": "garlic",
"original": "2 teaspoons of garlic",
"unit": "teaspoons",
"unitLong": "teaspoons",
"unitShort": "tsps"
},
{
"amount": 1,
"name": "olive oil",
"original": "1 teaspoon olive oil",
"unit": "teaspoon",
"unitLong": "teaspoon",
"unitShort": "tsps"
},
{
"amount": 1,
"name": "mushrooms",
"original": "1 cup mushrooms",
"unit": "cup",
"unitLong": "cup",
"unitShort": "cup"
},
{
"amount": 1,
"name": "cherry tomatoes",
"original": "1 cup cherry tomatoes",
"unit": "cup",
"unitLong": "cup",
"unitShort": "cup"
}
],
"name": "Green Beans with Mushrooms and Cherry Tomatoes",
"preparation": [
"Steam green beans until tender.",
"Drain and set aside. Sauté onion and garlic in a medium skillet coated with olive oil, until tender. About 2 to 3 minutes.",
"Add mushrooms and sauté until tender. Stir in green beans and tomotoes until heated."
],
"yield": 4,
"objectID": "0"
}
我的食谱数据 classes 设置如下:
Recipe.kt
@IgnoreExtraProperties
@Serializable
data class Recipe(
var difficulty: Int = 0,
var dishType: String? = null,
var duration: Int = 0,
var durationUnit: String? = null,
var image: String? = null,
var diet: String? = null,
var cuisine: String? = null,
var name: String? = null,
var ingredients: List<Ingredient> = emptyList(),
var preparation: List<String> = emptyList(),
var yield: Int = 0
) {
Ingredient.kt
@Serializable
data class Ingredient(
var amount: Int = 0,
var name: String? = null,
var original: String? = null, // Original text of the ingredient
var unit: String? = null,
var unitLong: String? = null,
var unitShort: String? = null
)
我从 Algolia 的 InstantSearch 入门指南Android 中获得的这段代码对索引中的数据进行了反序列化。
private val datasourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
hit.deserialize(Recipe.serializer()) // Problem line I assume
}
val pagedListConfig = PagedList.Config.Builder().setPageSize(50).build()
val recipes: LiveData<PagedList<Recipe>> =
LivePagedListBuilder(datasourceFactory, pagedListConfig).build()
val searchBox =
SearchBoxConnectorPagedList(searcher, listOf(recipes))
我尝试使用以下代码手动创建对象,但我 运行 在尝试创建成分列表时遇到问题。
val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
Recipe(
hit.json.getPrimitive("difficulty").content.toInt(),
hit.json.getPrimitive("dishType").content,
hit.json.getPrimitive("duration").content.toInt(),
hit.json.getPrimitive("durationUnit").content,
hit.json.getPrimitive("image").content,
hit.json.getPrimitive("diet").content,
hit.json.getPrimitive("cuisine").content,
hit.json.getPrimitive("name").content,
listOf(
Ingredient(
hit.json.getPrimitive("amount").content.toInt(),
hit.json.getPrimitive("name").content,
hit.json.getPrimitive("original").content,
hit.json.getPrimitive("unit").content,
hit.json.getPrimitive("unitLong").content,
hit.json.getPrimitive("unitShort").content
)
),
hit.json.getArray("preparation").content.map { prep -> prep.content },
hit.json.getPrimitive("yield").content.toInt()
)
}
我不是 100% 确定我是否正确地创建了 preparation 属性 成员以及整个创建成分列表的过程有副作用跟踪我。任何帮助将不胜感激,对于我的第一个 post 很长,我深表歉意。我已经为此做了几天,但我对下一步该做什么感到困惑。
正如您看到的这一行:
kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset -1: Failed to parse 'int'.
这里发生了 JsonDecodingException 异常,这就是它没有给出正确响应的原因。您必须检查所有数据 classes 是否与 JSON Object.
中的变量相同我发现你的数据有 1 个问题 class,首先检查这个 JSON 回复:
"amount": 1.5
现在检查您的数据 class,其中有 var amount: Int = 0
@Serializable
data class Ingredient(
var amount: Int = 0,
var name: String? = null,
var original: String? = null, // Original text of the ingredient
var unit: String? = null,
var unitLong: String? = null,
var unitShort: String? = null
)
此处JSON 对象在Float
中,而您正在将其存储在Int
中,这可能会导致异常。确保数据 class 中的所有值都正确。
或者为了变通,您只需将数据中的字符串设为所有变量 class 以检查所有响应是否正确显示,然后根据您的要求将它们转换为 Int、Float。