Android平台Retrofit 2解析无键嵌套JSON数组报错求助
解决Retrofit 2解析无键嵌套混合JSON数组的问题
嘿,我来帮你搞定这个Retrofit解析的坑!你遇到的错误根源是这个JSON结构太不规则了——它是一个混合类型的根数组,里面既有嵌套多层的数组,又有null和字符串,直接用普通的单一类型List(比如List<String>)去映射,Gson(默认转换器)肯定会懵,因为它预期每个元素都是字符串,但第一个元素却是数组,所以才会抛出Expected a string but was BEGIN_ARRAY的错误。
先拆解你的JSON结构
先把目标JSON拆解开,好让你清晰看到层级:
[ [ ["demo description", "demo", null, null, 1] ], null, "en" ]
整个根是一个数组,包含3个元素:
- 第1个元素:是一个数组,里面只有1个元素,而这个元素又是一个包含5个元素的数组(字符串、字符串、null、null、数字)
- 第2个元素:null
- 第3个元素:字符串"en"
解决方案:手动逐层解析(最可靠的方式)
因为结构太不规则,自动映射容易出问题,推荐用List<Object>接收整个响应,然后逐层强制类型转换解析:
1. 定义Retrofit接口(Kotlin示例)
interface YourApiService { @GET("your-api-endpoint") suspend fun fetchData(): List<Any> }
2. 调用接口并解析数据
拿到响应后,逐层拆解:
// 调用接口获取响应 val response = yourApiService.fetchData() // 先定义对应最内层数据的实体类 data class ContentItem( val description: String, val name: String, val unusedField1: Any?, val unusedField2: Any?, val id: Int ) // 解析第一个嵌套数组部分 val outerNestedArray = response[0] as List<*> // 拿到第一层嵌套数组 [[...]] val innerArray = outerNestedArray[0] as List<*> // 拿到第二层数组 [...] val contentItem = ContentItem( description = innerArray[0] as String, name = innerArray[1] as String, unusedField1 = innerArray[2], unusedField2 = innerArray[3], id = innerArray[4] as Int ) // 解析第三个元素:语言标识 val language = response[2] as String
3. Java版本解析示例
// 接口定义 public interface YourApiService { @GET("your-api-endpoint") Call<List<Object>> fetchData(); } // 调用并解析 yourApiService.fetchData().enqueue(new Callback<List<Object>>() { @Override public void onResponse(Call<List<Object>> call, Response<List<Object>> response) { if (response.isSuccessful() && response.body() != null) { List<Object> rootList = response.body(); // 解析嵌套数组 List<?> outerNestedArray = (List<?>) rootList.get(0); List<?> innerArray = (List<?>) outerNestedArray.get(0); String description = (String) innerArray.get(0); String name = (String) innerArray.get(1); Object unused1 = innerArray.get(2); Object unused2 = innerArray.get(3); int id = (int) innerArray.get(4); // 解析语言 String language = (String) rootList.get(2); } } @Override public void onFailure(Call<List<Object>> call, Throwable t) { // 处理请求失败逻辑 } });
额外提示
- 如果用Moshi而非Gson作为转换器,思路完全一致:用
List<Any>接收响应后逐层解析。 - 解析时建议加空安全判断(比如检查数组长度),避免出现数组越界或类型转换异常。
- 如果这个JSON结构是固定不变的,也可以自定义Gson TypeAdapter实现自动映射,但手动解析对这种不规则结构来说更简单直接。
内容的提问来源于stack exchange,提问作者Minh Nguyen
相关产品推荐
相关产品推荐

