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

Retrofit对接Spring Boot报错:Expected BEGIN_ARRAY but was BEGIN_OBJECT

解决Retrofit解析JSON时的Expected BEGIN_ARRAY but was BEGIN_OBJECT错误

首先看你的错误日志,核心问题非常明确:java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT——Gson期望解析一个JSON数组,但实际收到的是一个JSON对象。结合你提供的接口返回数据,我来拆解问题和解决方案:

问题根源

你的Retrofit接口IBrowseService定义的返回类型是Call<List<BrowseDTO>>,也就是期望服务器直接返回一个BrowseDTO的数组。但实际服务器返回的是一个包裹了数组的对象,结构是这样的:

{
  "content": [
    // 你的漫画数据数组
  ]
}

Gson尝试把整个对象当成数组解析,自然就报错了。另外还有一个隐藏问题:你的BrowseDTO结构和返回的数组元素完全不匹配,这个也得一起修正。

分步解决方案

1. 创建分页响应DTO类

首先需要一个类来匹配服务器返回的外层对象,用来接收包含数组的content字段:

public class BrowsePageResponse {
    private List<BrowseDTO> content;

    // Getter和Setter
    public List<BrowseDTO> getContent() {
        return content;
    }

    public void setContent(List<BrowseDTO> content) {
        this.content = content;
    }
}

2. 修改Retrofit接口的返回类型

把IBrowseService的返回类型从Call<List<BrowseDTO>>改成Call<BrowsePageResponse>:

public interface IBrowseService {
    @GET("/Browse/{pageNumber}")
    Call<BrowsePageResponse> getIssuesPaginated(
        @Path("pageNumber") int pageNumber);
}

3. 调整Presenter里的解析逻辑

在BrowseTaskFirst的doInBackground方法中,先获取外层响应对象,再提取里面的content数组:

@Override
protected List<BrowseDTO> doInBackground(Integer... integers) {
    IBrowseService iBrowseService = APIClient.createService(IBrowseService.class, Token.getInstance());
    Call<BrowsePageResponse> browseIssuesPage = iBrowseService.getIssuesPaginated(integers[0]);
    try{
        BrowsePageResponse response = browseIssuesPage.execute().body();
        if (response != null) {
            return response.getContent(); // 提取真正需要的数组
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

4. 修正BrowseDTO的结构

你的BrowseDTO现在是嵌套了IssueDTO和List<StockDTO>,但服务器返回的每个数组元素是平级的字段(比如issueTitle、condition等),所以必须把BrowseDTO改成和返回字段一一对应的结构:

public class BrowseDTO {
    private String issueTitle;
    private String description;
    private String condition;
    private int stockReferenceId;
    private int availableQuantity;
    private int seriesNumber;
    private double price;
    private String publisher;
    private String coverImage;

    // 生成所有字段的Getter和Setter方法
    public String getIssueTitle() {
        return issueTitle;
    }

    public void setIssueTitle(String issueTitle) {
        this.issueTitle = issueTitle;
    }

    // 其他字段的Getter/Setter同理,这里省略
}

验证修改

做完这些修改后,重启App测试:

  1. Retrofit会先解析外层的BrowsePageResponse对象
  2. 提取content字段里的数组,转换成List<BrowseDTO>
  3. 最终传递给loadFirst方法加载到RecyclerView中

这样就能解决解析错误,同时保证数据能正确映射到DTO类里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 14:49:07