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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:14:22