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

Spring Boot RestTemplate将JSON响应转换为实体类失败问题排查

问题排查与修正方案

错误原因

代码存在5处核心问题,导致反序列化失败:

  • 未匹配JSON最外层结构:接口返回的JSON最外层存在main包装节点,当前直接以Main.class作为反序列化目标,框架会直接把最外层JSON对象和Main类字段匹配,找不到test、response字段直接报错。
  • response字段类型与JSON结构完全不符:JSON中response是数组结构,数组元素是包含responseTime、redirects数字字段的对象,当前代码把response定义为单个自定义Response类型,且Response类中凭空定义了不存在于JSON结构的responseMap字段,完全无法匹配。
  • 日期字段缺少反序列化配置:Test类中Date字段是java.util.Date类型,JSON中对应值是yyyy-MM-dd格式的字符串,默认序列化框架无法直接将该格式字符串转为Date对象。
  • 字段命名匹配风险:Java字段命名规范为驼峰式首字母小写,当前Test类中Date、Id字段直接首字母大写,和框架默认的属性匹配规则存在冲突,容易出现字段找不到的问题。
  • 实体类缺少必要方法:RestTemplate默认使用Jackson做JSON序列化,需要实体类提供无参构造、对应字段的getter/setter才能通过反射完成属性赋值,当前代码未提供这些方法。

修正方案

按以下步骤修改即可:

  1. 新增最外层响应包装类,匹配JSON最外层的main节点
  2. 调整response字段类型:按照JSON数组结构,用List<Map<String, Object>>类型接收,既符合数组结构,也满足将response内容映射为Map(框架默认会用HashMap实例化Map接口)的需求;注意Map的值类型要设为Object,因为responseTime、redirects都是数字类型,设为String会触发类型转换错误。
  3. 为Test类的日期字段指定反序列化格式,通过注解绑定JSON中大写开头的字段名,将Java字段调整为符合规范的驼峰命名。
  4. 为所有实体类添加无参构造、对应字段的getter与setter。
  5. 修改RestTemplate调用代码,将反序列化目标类替换为新增的最外层包装类。

修正后完整代码

  1. 最外层响应类
public class ApiResponse {
    private Main main;

    public ApiResponse() {}

    public Main getMain() {
        return main;
    }

    public void setMain(Main main) {
        this.main = main;
    }
}
  1. Main实体类
import java.util.List;
import java.util.Map;

public class Main {
    private Test test;
    private List<Map<String, Object>> response;

    public Main() {}

    public Test getTest() {
        return test;
    }

    public void setTest(Test test) {
        this.test = test;
    }

    public List<Map<String, Object>> getResponse() {
        return response;
    }

    public void setResponse(List<Map<String, Object>> response) {
        this.response = response;
    }
}
  1. Test实体类
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;

public class Test {
    @JsonProperty("Date")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date date;

    @JsonProperty("Id")
    private Integer id;

    public Test() {}

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}
  1. 调整后的接口调用代码
HttpEntity<String> request = new HttpEntity<>(setHeaders());
ResponseEntity<ApiResponse> response = restTemplate.exchange(endpoint, HttpMethod.GET, request, ApiResponse.class);
// 调用getBody()拿到ApiResponse实例后,通过getMain()即可获取对应Main对象

补充说明:如果必须保留自定义Response类包装Map结构,不要在Response类中额外定义responseMap这类JSON中不存在的字段,可以直接让Response继承HashMap<String, Object>,再将Main类中的response字段类型改为List<Response>即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:01:08