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

如何用Retrofit(GsonConverterFactory)序列化JSON到GetDataResponse数据类?

解决方案

1. 定义基础数据类

先把JSON结构里的固定部分用常规Kotlin数据类定义:

data class GetDataResponse(
    val id: Int,
    val result: Result
)

data class Result(
    val list: List<ListItem>
)

data class ListItem(
    val user: User,
    val id: Int,
    val changes: Changes
)

data class User(
    val firstName: String,
    val lastName: String
)

data class OldNew(
    val old: String,
    val new: String
)

2. 解决Changes的混合类型序列化问题

原JSON中changes字段存在两种类型的值:单个OldNew对象(如firstName)、OldNew数组(如emails),这是自动序列化失败的核心原因。我们通过自定义Gson反序列化器来统一处理:

定义Changes类

data class Changes(
    val changesMap: Map<String, List<OldNew>>
)

编写自定义反序列化器

class ChangesDeserializer : JsonDeserializer<Changes> {
    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): Changes {
        val changesMap = mutableMapOf<String, List<OldNew>>()
        json?.asJsonObject?.entrySet()?.forEach { entry ->
            val key = entry.key
            val value = entry.value
            val oldNewList = when {
                value.isJsonObject -> {
                    // 单个OldNew对象转成单元素列表
                    listOf(context?.deserialize<OldNew>(value, OldNew::class.java)!!)
                }
                value.isJsonArray -> {
                    // 直接解析为OldNew列表
                    context?.deserialize<List<OldNew>>(value, object : TypeToken<List<OldNew>>() {}.type)!!
                }
                else -> emptyList()
            }
            changesMap[key] = oldNewList
        }
        return Changes(changesMap)
    }
}

3. 配置Gson并关联到Retrofit

把自定义反序列化器注册到Gson实例,再让Retrofit使用这个Gson:

val gson = GsonBuilder()
    .registerTypeAdapter(Changes::class.java, ChangesDeserializer())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl("你的接口基础URL")
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()

// 创建API服务实例
val apiService = retrofit.create(YourApiService::class.java)

4. 动态展示变更列表的用法

拿到Changes对象后,遍历changesMap即可统一处理所有变更:

// 示例:遍历打印所有变更
changes.changesMap.forEach { (fieldName, oldNewList) ->
    println("字段:$fieldName")
    oldNewList.forEach { oldNew ->
        println("  旧值:${oldNew.old},新值:${oldNew.new}")
    }
}

这样就能完美适配原JSON的混合结构,实现自动序列化,同时支持动态展示所有变更项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 11:48:59