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

RestTemplate反序列化嵌套List异常:如何实现完整映射?

问题描述

使用RestTemplate将JSON映射为Java对象时,仅能反序列化得到reservations为空数组的LockerReservations对象;当reservations列表包含数据时,反序列化直接失败。

相关代码与数据

LockerReservations实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LockerReservations {
    Locker locker;
    List<Reservation> reservations;
}

返回的JSON数据

[
    {
        "locker": {
            "id": 0,
            "size": "S"
        },
        "reservations": []
    },
    {
        "locker": {
            "id": 1,
            "size": "S"
        },
        "reservations": []
    },
    {
        "locker": {
            "id": 4,
            "size": "S"
        },
        "reservations": [
            {
                "id": 17,
                "start": "2023-03-14T06:37:07.006",
                "end": "2023-03-14T12:37:07.006",
                "user": {
                    "id": 1,
                    "name": "Kiemoon"
                },
                "locker": {
                    "id": 4,
                    "size": "S"
                }
            },
            {
                "id": 36,
                "start": "2023-03-14T14:37:07.006",
                "end": "2023-03-14T15:37:07.006",
                "user": {
                    "id": 1,
                    "name": "Kiemoon"
                },
                "locker": {
                    "id": 4,
                    "size": "S"
                }
            }
        ]
    } 
]

RestTemplate调用代码

public List<LockerReservations> getReservationsCheck2(Size size, LocalDateTime start, LocalDateTime end) {

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
    Map<String, Object> sizeTimeMap = new HashMap<>();
    sizeTimeMap.put("size", size.toString());
    sizeTimeMap.put("start", start.toString());
    sizeTimeMap.put("end", end.toString());
    HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(sizeTimeMap, httpHeaders);
    LockerReservations[] exchange = restTemplate.postForObject(url + "reservationsCheck", httpEntity, LockerReservations[].class);
    return Arrays.asList(exchange);
}

解决方案

1. 完善所有嵌套实体类的序列化配置

确保Locker、Reservation、User类都满足以下要求:

  • 有无参构造器(通过@NoArgsConstructor注解生成)
  • 字段具备可访问性(通过@Data生成getter/setter,或直接设为public)
  • 日期字段适配JSON格式

示例实体类实现:

// Locker类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Locker {
    private Integer id;
    private String size;
}

// User类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
}

// Reservation类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Reservation {
    private Integer id;
    @JsonProperty("start")
    private LocalDateTime startTime;
    @JsonProperty("end")
    private LocalDateTime endTime;
    private User user;
    private Locker locker;
}

2. 配置RestTemplate的Jackson消息转换器

Jackson默认不支持LocalDateTime类型的序列化/反序列化,需添加JavaTimeModule并配置对应日期格式:

@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    // 注册Java 8时间处理模块
    objectMapper.registerModule(new JavaTimeModule());
    // 禁用时间戳格式,使用字符串格式化
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    // 匹配JSON中的日期格式
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"));
    
    converter.setObjectMapper(objectMapper);
    // 替换默认的Jackson转换器
    restTemplate.getMessageConverters().replaceAll(c -> 
        c instanceof MappingJackson2HttpMessageConverter ? converter : c
    );
    
    return restTemplate;
}

3. 异常排查与调试

在调用代码中捕获异常并打印详细栈信息,精准定位反序列化失败的具体字段:

public List<LockerReservations> getReservationsCheck2(Size size, LocalDateTime start, LocalDateTime end) {
    try {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        Map<String, Object> sizeTimeMap = new HashMap<>();
        sizeTimeMap.put("size", size.toString());
        sizeTimeMap.put("start", start.toString());
        sizeTimeMap.put("end", end.toString());
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(sizeTimeMap, httpHeaders);
        LockerReservations[] exchange = restTemplate.postForObject(url + "reservationsCheck", httpEntity, LockerReservations[].class);
        return Arrays.asList(exchange);
    } catch (RestClientException e) {
        e.printStackTrace();
        throw new RuntimeException("反序列化失败", e);
    }
}

4. 字段匹配验证

确保实体类字段名与JSON中的键完全一致,若存在命名差异,使用@JsonProperty显式指定映射关系(例如JSON键为start,实体类字段为startTime时,添加@JsonProperty("start")注解)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:13:29