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

如何通过Retrofit获取API数据并反序列化为Kotlin List?解决序列化报错

问题根源

你遇到的报错是因为API实际返回的是单个DishResponse对象(JSON格式为{...}),但你的接口定义和序列化适配器都期望接收一个数组(JSON格式为[...]),导致Gson解析时出现类型不匹配。

解决方案

根据需求,提供两种可行的处理方式:

方式一:直接调整接口返回类型(推荐)

如果API确实只返回单个菜品数据,直接修改接口返回值为单个对象,之后手动包装成List即可:

  1. 修改接口定义:
interface DishesApi {
    @Headers(
        value = [
            "X-RapidAPI-Key: 05fefddc5amshe82caa1862a2f8cp15fb97jsn1ee9dd9eb288",
            "X-RapidAPI-Host: burgers1.p.rapidapi.com"
        ]
    )
    @GET("burgers")
    suspend fun getBurgers(): DishResponse
}
  1. 调用时转为List:
val singleDish = dishesApi.getBurgers()
val dishList = listOf(singleDish)

方式二:修改适配器兼容单个对象转List

如果必须让接口直接返回List<DishResponse>(比如后续API可能返回数组),修改序列化适配器的解析逻辑,判断JSON是对象还是数组:

  1. 更新DishResponseAdapter:
class DishResponseAdapter : JsonDeserializer<List<DishResponse>>, JsonSerializer<List<DishResponse>> {

    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): List<DishResponse> {
        json ?: return emptyList()
        return if (json.isJsonArray) {
            // 解析JSON数组
            Gson().fromJson(json, Array<DishResponse>::class.java).asList()
        } else {
            // 单个JSON对象包装成List
            listOf(Gson().fromJson(json, DishResponse::class.java))
        }
    }

    override fun serialize(
        src: List<DishResponse>?,
        typeOfSrc: Type?,
        context: JsonSerializationContext?
    ): JsonElement {
        return when (src) {
            null -> JsonNull.INSTANCE
            else -> Gson().toJsonTree(src) // 修复原错误:正确生成JSON数组而非字符串
        }
    }
}
  1. 确保Retrofit注册该适配器:
val gson = GsonBuilder()
    .registerTypeAdapter(object : TypeToken<List<DishResponse>>() {}.type, DishResponseAdapter())
    .create()

val retrofit = Retrofit.Builder()
    .baseUrl("https://burgers1.p.rapidapi.com/")
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
补充:确认数据类结构

确保DishResponse及嵌套类字段与JSON完全对应:

data class DishResponse(
    val id: Int,
    val name: String,
    val restaurant: String,
    val web: String,
    val description: String,
    val ingredients: List<String>,
    val addresses: List<Address>
)

data class Address(
    val addressId: Int,
    val number: String,
    val line1: String,
    val line2: String,
    val postcode: String,
    val country: String
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 03:54:15