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

将JSON反序列化为Record时出现JSON解析错误

解决Java Record作为Spring MVC DTO的反序列化报错问题

问题场景

在Spring MVC控制器中使用TransactionDTO(Java Record)接收JSON请求体时,出现以下报错:

Could not resolve parameter [0] in private org.springframework.http.ResponseEntity<com.web.store.app.backend.dto.TransactionDTO> com.web.store.app.backend.controller.TransactionController.saveTransaction(com.web.store.app.backend.dto.TransactionDTO): JSON parse error: Can not set final java.util.List field com.web.store.app.backend.dto.TransactionDTO.productIds to java.util.ArrayList

将Record改为普通类并移除final修饰符后可正常运行,但希望继续使用Record作为DTO。

核心原因

Java Record的所有字段默认是final的,低版本Jackson(2.12以下)不支持通过Record的构造器完成反序列化,会尝试直接反射修改final字段,导致报错。另外,控制器方法使用private修饰符不符合Spring MVC规范,可能引发潜在问题。

解决方案

1. 修正控制器方法的访问权限

Spring MVC控制器方法必须为public,否则框架无法正确调用。修改控制器代码:

@PostMapping(value = "add")
public ResponseEntity<TransactionDTO> saveTransaction(@Valid @RequestBody TransactionDTO transactionDTO) {
    return transactionService.saveTransaction(transactionDTO).map(
            transaction -> ResponseEntity.status(HttpStatus.CREATED).body(transaction)).orElseGet(
            () -> ResponseEntity.status(HttpStatus.BAD_REQUEST).build());
}

2. 升级Spring Boot版本(推荐)

Jackson从2.12版本开始正式支持Java Record的反序列化,对应Spring Boot 2.4及以上版本。直接升级Spring Boot版本到2.4+,Jackson会自动使用Record的构造器创建实例,无需额外配置。

3. 低版本环境下的兼容配置(无法升级时)

如果无法升级Spring Boot版本,可通过以下两种方式解决:

方式一:自定义Jackson ObjectMapper

添加配置类,启用Record支持:

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // 处理日期时间类型
        mapper.registerModule(new JavaTimeModule());
        // 启用Record支持
        mapper.enable(MapperFeature.SUPPORT_RECORD_GETTERS);
        // 全局配置蛇形命名(可根据需求选择)
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        return mapper;
    }
}

方式二:为Record添加显式构造器

给Record添加带@JsonCreator注解的构造器,并为每个参数指定@JsonProperty:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record TransactionDTO(String id, Long userId,
                             @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mmXXX", shape = JsonFormat.Shape.STRING)
                             ZonedDateTime createdAt, List<String> productIds) {

    @JsonCreator
    public TransactionDTO(
            @JsonProperty("id") String id,
            @JsonProperty("user_id") Long userId,
            @JsonProperty("created_at") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mmXXX", shape = JsonFormat.Shape.STRING) ZonedDateTime createdAt,
            @JsonProperty("product_ids") List<String> productIds) {
        this.id = id;
        this.userId = userId;
        this.createdAt = createdAt;
        this.productIds = productIds;
    }
}

验证

使用原curl命令测试:

curl --location 'localhost:8080/transaction/api/add' \
--header 'Content-Type: application/json' \
--data '{
    "id": "TRNS03",
    "user_id": 1,
    "created_at":"2023-03-19T06:33-06:00",
    "product_ids":["PRD003"]
}'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:49:53