如何在Kotlin的Retrofit中将多个JSON对象转为数组并适配RecyclerView
问题:在Kotlin+Retrofit中解析键为ID的JSON对象为数组,用于RecyclerView展示
我需要在RecyclerView中展示两支球队的球员列表,但接口返回的球员数据是以JSON对象(键为球员ID)的形式存在,而非标准JSON数组。接口返回的示例数据如下:
"Teams":{ "4":{ "Name_Full":"India", "Name_Short":"IND", "Players":{ "3852":{ "Position":"1", "Name_Full":"Rohit Sharma", "Iscaptain":true, "Batting":{ "Style":"RHB", "Average":"47.88", "Strikerate":"88.46", "Runs":"7806" }, "Bowling":{ "Style":"OB", "Average":"64.37", "Economyrate":"5.21", "Wickets":"8" } }, "3722":{ "Position":"2", "Name_Full":"Shikhar Dhawan", "Batting":{ "Style":"LHB", "Average":"45.36", "Strikerate":"93.59", "Runs":"5172" }, "Bowling":{ "Style":"OB", "Average":"0", "Economyrate":"0", "Wickets":"0" } } } } }
解决方案
方法1:自定义Gson TypeAdapter自动转换
适合希望在解析阶段直接将对象转成List的场景,无需后续手动处理。
1. 定义对应的数据类
写出匹配JSON结构的数据类,通过注解指定Players字段使用自定义解析器:
data class TeamResponse( val Teams: Map<String, Team> ) data class Team( val Name_Full: String, val Name_Short: String, @JsonAdapter(PlayerListTypeAdapter::class) val Players: List<Player> ) data class Player( val Position: String, val Name_Full: String, val Iscaptain: Boolean?, val Batting: BattingStats, val Bowling: BowlingStats ) data class BattingStats( val Style: String, val Average: String, val Strikerate: String, val Runs: String ) data class BowlingStats( val Style: String, val Average: String, val Economyrate: String, val Wickets: String )
2. 编写TypeAdapter实现对象转List
创建PlayerListTypeAdapter,负责将JSON对象解析为List<Player>,同时按Position排序保证展示顺序:
class PlayerListTypeAdapter : TypeAdapter<List<Player>>() { override fun write(out: JsonWriter, value: List<Player>) { // 无需序列化可留空,如需序列化自行实现逻辑 } override fun read(`in`: JsonReader): List<Player> { val playerMap = mutableMapOf<String, Player>() val gson = Gson() `in`.beginObject() while (`in`.hasNext()) { val playerId = `in`.nextName() val player = gson.fromJson(`in`, Player::class.java) playerMap[playerId] = player } `in`.endObject() return playerMap.values.sortedBy { it.Position.toInt() } } }
3. 配置Retrofit使用自定义Gson
构建Retrofit实例时注册自定义TypeAdapter:
val customGson = GsonBuilder() .registerTypeAdapter(List::class.java, PlayerListTypeAdapter()) .create() val retrofit = Retrofit.Builder() .baseUrl("你的接口基础地址") .addConverterFactory(GsonConverterFactory.create(customGson)) .build()
调用接口后,Team中的Players直接是List,可直接传给RecyclerView的Adapter。
方法2:解析为Map后手动转List
不想自定义TypeAdapter时,可直接将Players解析为Map<String, Player>,获取数据后手动转换:
1. 修改数据类
将Team中的Players改为Map类型:
data class Team( val Name_Full: String, val Name_Short: String, val Players: Map<String, Player> )
2. 接口回调中处理转换
在Retrofit回调里把Map值转成List并排序:
apiService.getTeamData().enqueue(object : Callback<TeamResponse> { override fun onResponse(call: Call<TeamResponse>, response: Response<TeamResponse>) { response.body()?.let { teamResp -> val allPlayers = mutableListOf<Player>() teamResp.Teams.values.forEach { team -> val sortedPlayers = team.Players.values.sortedBy { it.Position.toInt() } allPlayers.addAll(sortedPlayers) } recyclerView.adapter = PlayerAdapter(allPlayers) } } override fun onFailure(call: Call<TeamResponse>, t: Throwable) { // 处理请求失败逻辑 } })
内容的提问来源于stack exchange,提问作者KarthikaRajesh
相关产品推荐
相关产品推荐

