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

如何使用GSON库将指定JSON转换为Pokemon列表?适配Retrofit接口

解决Retrofit解析键值对JSON为Pokemon列表的问题

这个场景很常见——后端返回的是键值对结构的JSON,但我们的业务需要的是列表形式的Pokemon集合。下面给你三种可行的解决办法,按需选择:

方案1:修改接口返回类型,手动转换(最直观简单)

后端返回的JSON本质是一个Map<String, Pokemon>,我们先让Retrofit直接解析成Map,再提取值转成List即可:

  1. 调整Retrofit接口的返回类型:
@GET("/pokemon")
fun getPokemon(): Call<Map<String, Pokemon>>
  1. 调用接口时转换为列表:
val call = apiService.getPokemon()
call.enqueue(object : Callback<Map<String, Pokemon>> {
    override fun onResponse(call: Call<Map<String, Pokemon>>, response: Response<Map<String, Pokemon>>) {
        if (response.isSuccessful) {
            // 提取Map中的所有值,转成List
            val pokemonList = response.body()?.values?.toList() ?: emptyList()
            // 这里就拿到了你需要的[Pokemon@1, Pokemon@2, Pokemon@3]
        }
    }

    override fun onFailure(call: Call<Map<String, Pokemon>>, t: Throwable) {
        // 处理请求失败逻辑
    }
})

方案2:自定义Gson TypeAdapter,自动转换(一劳永逸)

如果你的项目中经常需要这种“键值对转列表”的解析,可以自定义Gson的适配器,让它自动完成转换,不用每次手动处理:

  1. 编写自定义TypeAdapter:
class PokemonListTypeAdapter : TypeAdapter<List<Pokemon>>() {
    override fun write(out: JsonWriter, value: List<Pokemon>?) {
        // 我们只需要解析JSON,不需要序列化列表,所以直接抛出不支持异常即可
        throw UnsupportedOperationException("序列化列表为键值对JSON暂不支持")
    }

    override fun read(`in`: JsonReader): List<Pokemon> {
        val pokemonList = mutableListOf<Pokemon>()
        `in`.beginObject()
        // 遍历JSON对象的所有键值对,跳过键名,只解析值为Pokemon对象
        while (`in`.hasNext()) {
            `in`.nextName() // 跳过Pikachu、Pichu这类键名
            val pokemon = Gson().fromJson(`in`, Pokemon::class.java)
            pokemonList.add(pokemon)
        }
        `in`.endObject()
        return pokemonList
    }
}
  1. 创建Retrofit实例时注册这个适配器:
// 配置Gson,注册自定义适配器
val customGson = GsonBuilder()
    .registerTypeAdapter(
        object : TypeToken<List<Pokemon>>() {}.type,
        PokemonListTypeAdapter()
    )
    .create()

// 初始化Retrofit
val retrofit = Retrofit.Builder()
    .baseUrl("你的BaseUrl")
    .addConverterFactory(GsonConverterFactory.create(customGson))
    .build()
  1. 保持原接口定义不变:
@GET("/pokemon")
fun getPokemon(): Call<List<Pokemon>>

之后调用接口时,Gson会自动把后端的键值对JSON解析成你需要的List<Pokemon>。

方案3:手动解析ResponseBody(无侵入式)

如果不想修改Gson配置或接口返回类型,也可以直接获取原始的ResponseBody手动解析:

  1. 修改接口返回类型为ResponseBody:
@GET("/pokemon")
fun getPokemon(): Call<ResponseBody>
  1. 手动解析JSON字符串:
val call = apiService.getPokemon()
call.enqueue(object : Callback<ResponseBody> {
    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
        if (response.isSuccessful) {
            val jsonString = response.body()?.string()
            jsonString?.let {
                val gson = Gson()
                // 先解析成Map,再转成List
                val pokemonMap = gson.fromJson(it, object : TypeToken<Map<String, Pokemon>>() {}.type)
                val pokemonList = pokemonMap.values.toList()
                // 得到目标列表
            }
        }
    }

    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
        // 处理失败逻辑
    }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:32:21