You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin:含不确定键的JSON转Data Class时Map字段为空求助

解决方案

你的问题核心是JSON采用了混合结构:既有固定字段className,又有动态数字键("0"、"1")对应EachClass对象,而Gson默认无法自动将这些动态键映射到Orders类的classes属性上,导致classes始终为null。下面是两种优雅的解决方法:


方法一:自定义Json反序列化器

保持你现有的Data Class结构不变,通过实现JsonDeserializer来手动处理JSON字段的映射逻辑:

1. 实现反序列化器

import com.google.gson.*
import java.lang.reflect.Type

class OrdersDeserializer : JsonDeserializer<Orders> {
    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): Orders {
        val jsonObject = json?.asJsonObject ?: throw JsonParseException("无效的JSON格式")
        var className: String? = null
        val classesMap = mutableMapOf<String, EachClass>()
        val gson = Gson()

        // 遍历JSON所有键值对
        for ((key, value) in jsonObject.entrySet()) {
            when (key) {
                "className" -> className = value.asString
                else -> {
                    // 将动态键对应的JSON对象转为EachClass实例
                    val eachClass = gson.fromJson(value, EachClass::class.java)
                    classesMap[key] = eachClass
                }
            }
        }

        return Orders(className, classesMap)
    }
}

2. 注册反序列化器并反序列化

创建Gson实例时注册自定义的反序列化器,然后正常解析JSON:

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

// 假设jsonString是你的原始JSON字符串
val orders = gson.fromJson(jsonString, Orders::class.java)

方法二:使用@JsonAdapter注解简化注册

如果你不想每次创建Gson实例都手动注册反序列化器,可以直接在Orders类上添加@JsonAdapter注解,让Gson自动识别:

import com.google.gson.annotations.JsonAdapter

@JsonAdapter(OrdersDeserializer::class)
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
)

之后直接使用默认Gson实例即可完成解析:

val orders = Gson().fromJson(jsonString, Orders::class.java)

为什么原有方案失效?

Gson的默认映射规则是严格匹配字段名:你的Orders类定义了classes属性,但原始JSON中并没有名为classes的字段,那些动态数字键无法自动被识别为classes的Map元素,因此classes始终为null。自定义反序列化器的作用就是手动将这些动态键值对收集到classesMap中,同时保留className字段的映射。

内容的提问来源于stack exchange,提问作者JackWu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:35:18