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

Android解决API返回Meta字段为对象/数组的Gson解析异常问题

解决Retrofit+Gson解析Meta字段类型不一致问题

问题背景

现有Kotlin数据类定义如下:

data class Weather (
  val category: String,
  val id: String,
  val meta: Meta
)

data class Meta (
  val id: String,
  val name: String,
  val details: String
)

API返回的JSON中,meta字段存在两种格式:非空时为对象,为空时为数组([]),导致Gson解析时抛出异常:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY

因无法修改API,需在客户端通过自定义Gson解析逻辑解决该问题。

解决方案

方法一:自定义JsonDeserializer

创建MetaDeserializer类实现JsonDeserializer<Meta>,在解析时判断JSON元素类型:

class MetaDeserializer : JsonDeserializer<Meta> {
    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): Meta {
        json?.let {
            // 遇到数组时返回默认Meta对象(或根据需求返回null,需修改数据类meta为可空类型)
            if (it.isJsonArray) {
                return Meta(id = "", name = "", details = "")
            }
            // 正常解析对象类型
            return context?.deserialize(it, Meta::class.java) ?: Meta("", "", "")
        }
        return Meta("", "", "")
    }
}

构建Gson实例时注册该解析器,再配置给Retrofit:

val gson = GsonBuilder()
    .registerTypeAdapter(Meta::class.java, MetaDeserializer())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()

方法二:自定义TypeAdapter

通过TypeAdapter更灵活地处理序列化与反序列化逻辑:

class MetaTypeAdapter : TypeAdapter<Meta>() {
    override fun write(out: JsonWriter?, value: Meta?) {
        // 序列化逻辑(若无需自定义可直接使用默认Gson序列化)
        val defaultGson = Gson()
        out?.jsonValue(defaultGson.toJson(value))
    }

    override fun read(`in`: JsonReader?): Meta {
        `in`?.let {
            return when (it.peek()) {
                JsonToken.BEGIN_OBJECT -> Gson().fromJson(it, Meta::class.java)
                JsonToken.BEGIN_ARRAY -> {
                    // 跳过空数组,返回默认对象
                    it.skipValue()
                    Meta(id = "", name = "", details = "")
                }
                else -> Meta("", "", "")
            }
        }
        return Meta("", "", "")
    }
}

注册方式与方法一致:

val gson = GsonBuilder()
    .registerTypeAdapter(Meta::class.java, MetaTypeAdapter())
    .create()

可选优化:允许Meta为可空类型

如果业务允许meta字段为空,可修改数据类将meta设为可空:

data class Weather (
  val category: String,
  val id: String,
  val meta: Meta?
)

此时在解析器中遇到数组时直接返回null即可:

if (it.isJsonArray) {
    return null
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:31:06