返回

Kotlin JSON解析: 模型转换实战指南

Android

JSON对象到Kotlin类模型的转换方法

数据交互中,常常会遇到将 JSON 数据转换成应用中可操作的对象的情况。在 Android 开发中,处理服务器返回的 JSON 数据并将其转换为 Kotlin 类模型是一个常见需求。这篇文章将分析一个实际案例,并提供有效的解决方案。

问题分析

开发者尝试将 JSON 数组转换成 QuestionModel 类的对象数组,但遇到了 com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonArray 错误。这表明 Gson 预期接收一个 JSON 对象,但实际上得到的是 JSON 数组。查看提供的代码可以发现,问题源于 answer_options 字段在 QuestionModel 中被定义为 JsonObject 类型,而实际 JSON 数据中 answer_options 是一个包含对象的 JSON 数组。

另外,JSON 数据结构的特性也是原因之一。“1”这个键对应的是一个 JsonArray, 里面是多个JsonObject, 而开发者试图将数组中每一个Json对象转换成QuestionModel时发生错误,期望的是整体JsonArray, 而非每一个JsonObject.

解决方案一:修改数据模型

answer_options 实际上是一个数组,因此最直接的方法是修改 QuestionModel 类来匹配 JSON 数据结构。可以将 answer_options 的类型改为 List<AnswerOptionModel>。 并且建立AnswerOptionModel这个数据类。

data class AnswerOptionModel(
    @SerializedName("id")
    @Expose
    var id: Int? = null,
    @SerializedName("answer")
    @Expose
    var answer: String? = null
)

data class QuestionModel (
    @SerializedName("question")
    @Expose
    var question: String? = null,

    @SerializedName("id")
    @Expose
    var id: Int? = null,

    @SerializedName("answer_options")
    @Expose
    var answer_options: List<AnswerOptionModel>? = null
)

代码示例

修改数据模型后,可以这样转换:

val testArray = tpsObject.getAsJsonObject("questions")[tpsSelection[0].toString()].asJsonArray
val questionList = Gson().fromJson(testArray.toString(), object : TypeToken<List<QuestionModel>>() {}.type) as List<QuestionModel>
questionList.forEach {
  Log.i("m", it.question.toString())
}

上述代码的关键在于使用了 TypeToken。它能正确地解析 JSON 数组为 List<QuestionModel>forEach循环用于打印每个问题的文字,便于调试。

解决方案二:手动遍历并解析

若由于特殊原因不能修改数据模型, 另一个方法就是遍历 JsonArray 并手动解析每个JsonObject,然后封装成集合。 这样的方法能够有效规避因模型定义问题引起的解析异常。

val testArray = tpsObject.getAsJsonObject("questions")[tpsSelection[0].toString()].asJsonArray
val questionList = mutableListOf<QuestionModel>()
for(i in 0 until testArray.size()){
    val questionModel =  Gson().fromJson(testArray[i].asJsonObject.toString(),QuestionModel::class.java)
    questionList.add(questionModel)
}

questionList.forEach {
    Log.i("m", it.question.toString())
}

该方法遍历数组, 将每一个JsonObject使用Gson转化为QuestionModel实例, 添加到列表中. 使用forEach循环打印 QuestionModel 实例的问题文本用于检查结果。

安全建议

  • 类型匹配: 确保 Kotlin 数据模型中的字段类型与 JSON 数据中的类型完全匹配。类型不匹配会导致 JsonSyntaxException 错误。
  • 容错处理: 对解析异常添加 try-catch 块,提高程序的健壮性。当出现解析错误的时候,及时处理。

总结

本文分析了 JSON 对象到 Kotlin 类模型的转换问题。通过修改数据模型或手动解析 JSON 数组两种方案,均可实现成功转换。选用哪种方式取决于实际需求和对代码可维护性的考虑。正确理解 JSON 结构并编写精确匹配的数据模型对数据处理至关重要。

这些策略在处理从服务器返回的JSON数据时提供有效的保障,确保数据被正确解析并转换为可操作的Kotlin对象。同时强调了匹配JSON数据结构和错误处理的重要性。