如何解析多类型API JSON响应并在Kotlin中创建对应数据模型?
Kotlin兼容多类型API响应的数据模型方案
问题背景
调用同一API时,携带不同参数会返回两种格式的JSON响应:
- 非空的对象集合(注:示例格式不符合标准JSON规范,缺少外层数组包裹):
{ "name": "my name", "family": "my family" }, { "name": "my name1", "family": "my family1" }
- 空数组:
[]
解决方案
1. 基础数据类定义
先定义单个数据项的模型:
data class Person( val name: String, val family: String )
2. 针对Gson的处理
如果API返回的非空响应是无外层数组的多个对象(如示例),需要自定义TypeAdapter兼容数组和零散对象两种格式;如果是标准数组格式(外层有[]),直接用List<Person>接收即可。
自定义适配器代码:
class PersonListTypeAdapter : TypeAdapter<List<Person>>() { private val personAdapter = Gson().getAdapter(Person::class.java) override fun write(out: JsonWriter, value: List<Person>?) { out.beginArray() value?.forEach { personAdapter.write(out, it) } out.endArray() } override fun read(`in`: JsonReader): List<Person> { val result = mutableListOf<Person>() when (`in`.peek()) { JsonToken.BEGIN_ARRAY -> { `in`.beginArray() while (`in`.hasNext()) { result.add(personAdapter.read(`in`)) } `in`.endArray() } JsonToken.BEGIN_OBJECT -> { do { result.add(personAdapter.read(`in`)) } while (`in`.peek() != JsonToken.END_DOCUMENT) } } return result } }
注册并使用:
val gson = GsonBuilder() .registerTypeAdapter(List::class.java, PersonListTypeAdapter()) .create() val personList = gson.fromJson(responseBody, object : TypeToken<List<Person>>() {}.type)
3. 针对Moshi的处理
通过自定义JsonAdapter实现格式兼容:
class PersonListAdapter { @FromJson fun fromJson(reader: JsonReader, delegate: JsonAdapter<Person>): List<Person> { val result = mutableListOf<Person>() when (reader.peek()) { JsonReader.Token.BEGIN_ARRAY -> { reader.beginArray() while (reader.hasNext()) { delegate.fromJson(reader)?.let { result.add(it) } } reader.endArray() } JsonReader.Token.BEGIN_OBJECT -> { do { delegate.fromJson(reader)?.let { result.add(it) } } while (reader.peek() != JsonReader.Token.END_DOCUMENT) } } return result } @ToJson fun toJson(writer: JsonWriter, value: List<Person>?, delegate: JsonAdapter<Person>) { writer.beginArray() value?.forEach { delegate.toJson(writer, it) } writer.endArray() } }
注册并使用:
val moshi = Moshi.Builder() .add(PersonListAdapter()) .build() val listAdapter = moshi.adapter<List<Person>>(Types.newParameterizedType(List::class.java, Person::class.java)) val personList = listAdapter.fromJson(responseBody)
补充提示
如果API返回的非空响应是标准JSON数组(外层包含[]),无需自定义适配器,直接用List<Person>作为解析类型即可,Gson和Moshi都能自动处理空数组和非空数组的情况。
内容的提问来源于stack exchange,提问作者Saeed Noshadi
相关产品推荐
相关产品推荐

