Retrofit解析嵌套数组JSON报错:Expected BEGIN_OBJECT but was BEGIN_ARRAY
问题分析
报错Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $[0]的核心原因是数据类/接口返回类型和实际JSON结构不匹配:
- 你期望根数组的元素是
PlayerData对象,但实际返回的JSON根数组的每个元素是另一个数组(嵌套数组结构:[[PlayerInfo对象], [PlayerInfo对象], ...]) - 额外定义的
PlayerData、Player数据类完全多余,因为JSON里没有对应的team、player键值对,直接是数组嵌套数组。
修正步骤
1. 调整API接口返回类型
修改ConnectedSleeper接口的返回类型,匹配JSON的List<List<PlayerInfo>>嵌套结构:
interface ConnectedSleeper { @GET("nflTeamDataArray") fun getPlayerData(): Call<List<List<PlayerInfo>>> // 改为嵌套列表类型 // 其余代码保持不变 companion object{ private const val BASE_URL = "http://10.0.2.2:8080/" fun create(): ConnectedSleeper { return Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(MoshiConverterFactory.create()) .build() .create(ConnectedSleeper::class.java) } } }
2. 修正PlayerInfo数据类的字段错误
JSON里的age是数字类型(如38),但你定义成了String?,会导致解析失败;另外postion存在拼写错误,需修正为position:
@JsonClass(generateAdapter = true) data class PlayerInfo( @Json(name = "birth_date") val birthDate: String?, @Json(name = "full_name") val fullName: String?, @Json(name = "college") val college: String?, @Json(name = "team") val team : String?, @Json(name = "position") val position: String?, // 修正拼写错误 @Json(name = "number") val number: Int?, @Json(name = "age") val age: Int?, // 改为Int类型,匹配JSON的数字格式 @Json(name = "weight") val weight: String?, @Json(name = "height") val height: String? ): java.io.Serializable
3. 移除冗余数据类
直接删除PlayerData.kt文件中的PlayerData和Player类,这两个类和实际JSON结构完全不对应,属于无效定义。
4. 调整MainActivity的响应处理逻辑
现在响应体是List<List<PlayerInfo>>,可以将嵌套列表扁平化为单一列表,方便RecyclerView使用:
sleeperConnect.getPlayerData() .enqueue(object : Callback<List<List<PlayerInfo>>> { override fun onResponse( call: Call<List<List<PlayerInfo>>>, response: Response<List<List<PlayerInfo>>> ) { if (response.isSuccessful) { val nestedPlayerList = response.body() // 将嵌套列表扁平化为单一列表 val flatPlayerList = nestedPlayerList?.flatten() ?: emptyList() Log.d("Response", "onResponse: 共解析${flatPlayerList.size}个球员数据") // 给RecyclerView设置适配器 val adapter = CustomAdapter(flatPlayerList) recyclerview.adapter = adapter } } override fun onFailure(call: Call<List<List<PlayerInfo>>>, t: Throwable) { Log.d("Draft time Activity ", "onFailure: " + t.message) } })
验证逻辑
修改完成后,Moshi会正确解析JSON结构:
- 根数组的每个元素被识别为
List<PlayerInfo>类型的数组 - 每个子数组内的对象会匹配修正后的
PlayerInfo数据类字段
内容的提问来源于stack exchange,提问作者Zmoney1999
相关产品推荐
相关产品推荐

