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

使用Retrofit2处理对象数组响应时遇JSON解析错误求助

解决Retrofit解析报错:Expected BEGIN_ARRAY but was BEGIN_OBJECT

老兄,我太懂你这种反复踩坑、试遍示例还是卡壳的憋屈了!这个报错其实是Retrofit最常见的「解析类型不匹配」问题,咱们一步步把它捋清楚、解决掉。

先搞懂报错本质

你说后端返回的是JSON对象数组,但报错提示「期望是数组(BEGIN_ARRAY),实际拿到的是对象(BEGIN_OBJECT)」——这说明你在Retrofit接口里声明的返回类型,和后端真实返回的JSON根节点类型不匹配。大概率是你以为后端直接返回纯数组,但实际上它返回的是一个包裹了数组的JSON对象。

举个直观的例子:

  • 你预期的返回(纯数组):
    [{"id":1, "amount":100}, {"id":2, "amount":200}]
    
  • 但后端实际返回的(带包裹的对象):
    {
      "code":200,
      "message":"success",
      "data": [{"id":1, "amount":100}, {"id":2, "amount":200}]
    }
    

这时候你用Call<List<Transfer>>去接收,自然会报错,因为根节点是{}对象,不是[]数组。

一步步解决问题

1. 先确认后端真实返回的JSON结构

别光听后端描述,自己动手验证最靠谱:

  • 用Postman、curl直接调用pendingTransfers接口,复制完整返回内容;
  • 或者临时修改Retrofit接口,先接收原始响应体打印真实JSON:
    @Headers("Content-Type: application/json")
    @POST("pendingTransfers")
    Call<ResponseBody> getPendingTransfers();
    
    然后在回调里输出真实内容:
    yourWebAPIService.getPendingTransfers().enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccessful()) {
                try {
                    String realJson = response.body().string();
                    Log.d("DEBUG", "后端真实返回: " + realJson);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            t.printStackTrace();
        }
    });
    

2. 根据真实JSON调整代码

  • 如果真实返回是纯数组:
    检查你的Model类(就是你之前Call<L...>里的泛型类)字段是否和JSON完全匹配,比如字段名、类型有没有写错,必要时用@SerializedName注解处理命名不一致:

    public class Transfer {
        @SerializedName("id")
        private int transferId; // 若JSON键是id,变量名不同时需要注解
        @SerializedName("amount")
        private double amount;
    
        // getters & setters
    }
    

    接口保持Call<List<Transfer>>即可。

  • 如果真实返回是包裹数组的对象:
    创建一个「响应包装类」,把数组作为对象的一个字段:

    public class PendingTransferResponse {
        @SerializedName("data") // 对应后端返回里数组的键名,比如data/pendingTransfers等
        private List<Transfer> transfers;
        // 可额外添加后端返回的其他字段,比如code、message
        private int code;
        private String message;
    
        // getters & setters
    }
    

    然后修改接口:

    @Headers("Content-Type: application/json")
    @POST("pendingTransfers")
    Call<PendingTransferResponse> getPendingTransfers();
    

    这样解析时就能匹配根节点的对象,再从里面取出数组。

最后提个小提醒

以后遇到解析类问题,第一步永远是确认真实的返回JSON结构,很多时候坑都出在「自己以为的返回」和「实际返回」不一致上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:30:19