Retrofit2与Gson:跳过无用根JSON节点反序列化数据
跳过无用根JSON节点直接解析内容的方案
当然可以!调用第三方API遇到这种外层冗余的JSON节点太常见了,咱们有好几种靠谱的方法能跳过那个多余的Response类,直接把内部字段解析到你想要的MyResponseClass里。
方法一:直接让JsonToKotlinClass生成目标类
最直接的方式就是修改插件的生成规则,让它自动扁平化根节点:
- 打开Android Studio的设置(
File > Settings > Plugins > JsonToKotlinClass > Settings) - 找到**「Root Element Handling」相关选项,选择「Flatten Root Element」**(不同版本插件的选项名称可能略有差异)
- 把你的原始JSON响应粘贴进去,插件就会自动提取
response节点下的字段,直接生成:
同时也会生成data class MyResponseClass( val status: Status, val configuration: Configuration )Status和Configuration这两个内部数据类,完美跳过中间的Response类。
方法二:解析时手动跳过冗余节点(适合已生成类的场景)
如果已经用插件生成了原来的四个类,或者不想修改插件设置,可以在解析阶段手动定位到response节点再解析:
Gson示例
val gson = Gson() // 先把原始JSON解析成JsonObject val rawJsonObject = gson.fromJson(apiResponseString, JsonObject::class.java) // 取出response节点的JSON字符串 val targetJson = rawJsonObject.getAsJsonObject("response").toString() // 直接解析成目标MyResponseClass(注意这个类要包含status和configuration字段) val myResponse = gson.fromJson(targetJson, MyResponseClass::class.java)
Moshi示例
val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter(JsonObject::class.java) val rawJsonObject = jsonAdapter.fromJson(apiResponseString) // 取出response节点 val targetJsonObject = rawJsonObject?.getAsJsonObject("response") // 解析成目标类 val targetAdapter = moshi.adapter(MyResponseClass::class.java) val myResponse = targetAdapter.fromJson(targetJsonObject.toString())
方法三:自定义解析适配器(优雅的长期方案)
如果这个API的所有响应都带有这个外层response节点,写一个自定义适配器可以统一处理,避免重复代码:
以Gson为例,实现一个TypeAdapterFactory:
class SkipRootResponseFactory : TypeAdapterFactory { override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? { val delegateAdapter = gson.getDelegateAdapter(this, type) return object : TypeAdapter<T>() { override fun write(out: JsonWriter, value: T?) { delegateAdapter.write(out, value) } override fun read(`in`: JsonReader): T { // 跳过外层的response节点 `in`.beginObject() while (`in`.nextName() != "response") { `in`.skipValue() } val result = delegateAdapter.read(`in`) `in`.endObject() return result } } } }
初始化Gson时注册这个工厂:
val gson = GsonBuilder() .registerTypeAdapterFactory(SkipRootResponseFactory()) .create() // 现在可以直接把原始JSON解析到目标类 val myResponse = gson.fromJson(apiResponseString, MyResponseClass::class.java)
这样以后所有带外层response节点的响应都能自动跳过冗余节点,直接解析到你想要的类结构里。
内容的提问来源于stack exchange,提问作者giozh
相关产品推荐
相关产品推荐

