Spring RESTController中Java Record反序列化报无唯一构造函数异常
问题解决方案
不需要编写自定义反序列化器,按以下步骤排查调整即可快速解决问题。
两个报错的核心原因:
- 初始运行时uuid字段为null,核心是Controller方法参数未加
@RequestBody注解,Spring未走Jackson JSON反序列化链路,而是用普通JavaBean参数解析逻辑处理请求,本身对Record兼容性差,也不会自动完成JSON字符串到UUID的类型转换。 - 新增构造函数后报找不到唯一构造器,是因为Record存在两个参数列表不同的全参构造器,Spring无法判定哪个是反序列化时使用的主构造器。
方案1:最简实现(推荐)
- 删掉你额外新增的String参数构造函数,保留最原始的Record定义即可:
public record Order(UUID uuid, List<OrderItem> items) {}
- 给Controller方法的Order参数加上
@RequestBody注解,明确告知Spring该参数从请求体JSON解析:
@PostMapping(value = "/allocations") public Allocation allocate(@RequestBody Order order) throws Exception { return planningService.allocate(order); }
如果使用的是Spring Boot 2.6及以上版本,以上两步修改后即可正常解析请求:框架默认已适配Java Record,且Jackson内置了String到UUID的自动反序列化规则,你提供的请求体可以直接转换为Order实例。
如果使用的是更低版本的Spring Boot,只要确保项目引入的Jackson版本不低于2.12,手动给ObjectMapper注册JDK8模块即可:
@Bean public ObjectMapper customObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Jdk8Module()); return mapper; }
方案2:需保留额外构造函数的场景
如果业务逻辑确实需要使用接收String类型uuid的构造函数,不需要删除该构造函数,只需在Record的主构造器上添加@JsonCreator注解,明确指定Jackson反序列化时使用的构造器即可:
public record Order(UUID uuid, List<OrderItem> items) { // 业务用自定义构造函数 public Order(String uuid, List<OrderItem> items) { this(UUID.fromString(uuid), items); } // 标记JSON反序列化使用的主构造器 @JsonCreator public Order {} }
同样需要保证Controller参数上添加了@RequestBody注解,即可正常完成反序列化。
注意:不要为了基础类型转换给Record额外添加构造函数,只要走正确的JSON反序列化链路,Jackson默认支持UUID、Java 8时间类等常用类型的字符串自动转换,无需额外编写转换逻辑。
内容的提问来源于stack exchange,提问作者Leos Literak
相关产品推荐
相关产品推荐

