Kotlin+Spring场景下如何用同一数据类解析不同类型的results字段
解决方案
可以通过自定义JSON解析适配器的方式,使用同一个数据类兼容results字段的对象/数组两种返回类型,无需为两个API单独定义数据类。
实现步骤(基于Gson框架)
1. 自定义类型适配器
新建PersonListTypeAdapter类,用于自动识别节点类型,单个对象会被自动包装为列表:
import com.google.gson.Gson import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter class PersonListTypeAdapter : TypeAdapter<ArrayList<Person>>() { override fun read(reader: JsonReader): ArrayList<Person> { val personList = arrayListOf<Person>() when (reader.peek()) { // 匹配到数组类型,遍历解析所有元素 JsonToken.BEGIN_ARRAY -> { reader.beginArray() while (reader.hasNext()) { val person = sharedGson.fromJson(reader, Person::class.java) personList.add(person) } reader.endArray() } // 匹配到对象类型,解析后直接加入列表 JsonToken.BEGIN_OBJECT -> { val person = sharedGson.fromJson(reader, Person::class.java) personList.add(person) } // 空值/其他异常类型直接返回空列表 else -> reader.skipValue() } return personList } override fun write(writer: JsonWriter, value: ArrayList<Person>?) { if (value == null) { writer.nullValue() return } // 序列化时统一按数组格式输出,按需可修改 writer.beginArray() value.forEach { sharedGson.toJson(it, Person::class.java, writer) } writer.endArray() } companion object { // 若项目有自定义Gson配置,替换为项目统一的Gson实例即可 private val sharedGson = Gson() } }
2. 给数据类字段绑定适配器
修改原有Result数据类,给persons字段加上@JsonAdapter注解:
data class Result( @SerializedName("results") @JsonAdapter(PersonListTypeAdapter::class) var persons: ArrayList<Person> = ArrayList() )
效果说明
- 调用2号API返回
results为数组时,会正常解析为对应的Person列表存入persons字段 - 调用1号API返回
results为单个对象时,适配器会自动将该对象包装为长度为1的ArrayList存入persons字段,不会抛出类型不匹配异常
注意事项
- 该方案仅解决
results字段的类型(对象/数组)不一致问题,若两个API返回的results内部字段结构不一致,仍需单独做结构兼容 - 若使用Moshi、Jackson等其他解析框架,可通过对应框架的自定义序列化/反序列化适配器能力实现相同逻辑,思路一致
内容的提问来源于stack exchange,提问作者zasaz
相关产品推荐
相关产品推荐

