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
相关产品推荐
相关产品推荐

