如何配置Jackson实现单字段Java Record的扁平化JSON序列化与反序列化
解决方案:利用Jackson的
@JsonValue和@JsonCreator实现扁平化序列化/反序列化 针对你遇到的Jackson嵌套序列化问题,同时满足保留AggregateId类、仅字段访问、无需自定义序列化器的需求,最简便的方案是在AggregateId这个Record上添加两个Jackson注解,直接指定它的序列化/反序列化逻辑:
1. 修改AggregateId Record
给Record的id字段添加@JsonValue,告诉Jackson直接将AggregateId实例序列化为id字段的UUID字符串;同时添加一个静态的@JsonCreator方法,用于将JSON中的字符串反序列化为AggregateId对象:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import java.util.UUID; public record AggregateId(@JsonValue UUID id) { @JsonCreator public static AggregateId fromString(String uuidStr) { return new AggregateId(UUID.fromString(uuidStr)); } }
2. 保持Aggregate类不变
你的Aggregate类无需任何修改,原有的@JsonCreator和@JsonProperty注解已经能正确配合上面的AggregateId配置工作:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class Aggregate { public final AggregateId aggregateId; @JsonCreator public Aggregate(@JsonProperty("aggregateId") AggregateId aggregateId) { this.aggregateId = aggregateId; } }
3. 验证效果
运行你的测试代码,现在序列化和反序列化都会生成/解析扁平化的JSON结构:
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class TestSerialization { public static void main(String[] args) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); String flatContent = """ { "aggregateId": "3f61aede-83dd-4049-a6ff-337887b6b807" } """; // 反序列化:字符串转Aggregate对象 Aggregate aggregate = objectMapper.readValue(flatContent, Aggregate.class); System.out.println(aggregate.aggregateId.id()); // 输出:3f61aede-83dd-4049-a6ff-337887b6b807 // 序列化:Aggregate对象转扁平化JSON String serialized = objectMapper.writeValueAsString(aggregate); System.out.println(serialized); // 输出:{"aggregateId":"3f61aede-83dd-4049-a6ff-337887b6b807"} } }
为什么@JsonUnwrapper不行?
你遇到的异常是Jackson 2.13.x版本的已知限制:构造器参数上无法使用@JsonUnwrapped注解,这个组合在当时的版本中还未被支持。而上面的方案完全避开了这个限制,同时能批量应用到所有类似的Record类型上,非常适合你提到的大量类似场景。
内容的提问来源于stack exchange,提问作者M. Dudek
相关产品推荐
相关产品推荐

