gson Android -使用Kotlin将具有不确定键的json转换为map

toe95027  于 2022-11-06  发布在  Android
关注(0)|答案(1)|浏览(201)

我有一个这样的json,我需要把它转换成数据类

{
    "0": {
        "id": "111",
        "type": "1",
        "items": [
            {
                "name": "Jack",
                "value": "26",
                "age": "0.0"
            },
            {
                "name": "Lisa",
                "value": "18",
                "age": "1.0"
            }
        ]
    },
    "1": {
        "id": "222",
        "type": "2",
        "items": [
            {
                "name": "Brown",
                "value": "23",
                "age": "30.0"
            },
            {
                "name": "Andy",
                "value": "18",
                "age": "23.0"
            }
        ]
    },
    "className": "A01"
}

我定义了以下数据类

data class Orders (
    val className: String?,
    val classes: Map<String, EachClass>
)

data class EachClass (
    val id: String,
    val type: String,
    val items: List<Person>
)

data class Person (
    val name: String,
    val value: String,
    val age: String
)

而结果总是表明
类名称=〉A01,类=〉空
我搜索了堆栈溢出,他们说使用TypeToken。但我有一个名为“className”的字段,无法使用EachClass对象转换

val type = object : TypeToken<EachClass>() {}.type
val obj = Gson().fromJson(data, EachClass::class.java)

我发现带有HashMap〈String,Object〉的TypeToken可以正常工作,但是很难看,我需要自己转换为数据类。
如果有人能告诉我正确的json转换方法,我将非常感激。谢谢!

jutyujz0

jutyujz01#

Gson没有为这种特定的情况提供内置的功能,所以你需要做一些手动转换,但幸运的是,对于你的用例来说,这并不是那么多的工作。
1.将JSON解析为Gson的JsonObject
1.删除className成员并将其存储起来以供以后使用
1.将JsonObject解析为Map<String, EachClass>
1.根据步骤2和3的结果构造Orders示例
完整的解决方案可能如下所示:

object OrdersDeserializer: JsonDeserializer<Orders> {
    private val classesType = object: TypeToken<Map<String, EachClass>>() {}.type

    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Orders {
        val jsonObject = json.asJsonObject
        val className = jsonObject.remove("className").asJsonPrimitive.asString

        val classes: Map<String, EachClass> = context.deserialize(jsonObject, classesType)
        return Orders(className, classes)
    }
}

然后,您可以按如下方式注册它:

val gson = GsonBuilder()
    .registerTypeAdapter(Orders::class.java, OrdersDeserializer)
    .create()

或者,您也可以将其转换为常规类,并在Orders类上使用Gson的@JsonAdapter注解,以避免手动注册反序列化程序。
注意:通常建议使用TypeAdapter而不是JsonSerializer/JsonDeserializer,以允许数据流以获得更好的性能。但是,由于您无论如何都需要在这里使用JsonObject(因此非流),因此使用TypeAdapter在这里没有提供优势,可能只会使实现稍微复杂化。

相关问题