如何让Jackson始终序列化完整对象或仅序列化ID而非交替模式?
解决Jackson @JsonIdentityInfo交替输出完整对象/ID的问题
你已经通过@JsonIdentityInfo注解(配置了PropertyGenerator和自定义EntityIdResolver)实现了基于ID的对象序列化/反序列化,但Jackson默认的「首次输出完整对象+ID,后续仅输出ID」的交替行为,给客户端的类型处理带来了麻烦。根据你的需求(客户端已掌握所有对象数据,希望统一输出ID或完整对象),分两种场景给出解决方案:
场景1:始终只输出ID(不输出完整对象内容)
如果客户端仅需要ID引用,不需要对象的完整内容,可以直接替换@JsonIdentityInfo的逻辑,改用自定义序列化器固定输出对象的id属性:
- 编写针对
MyClass的专属序列化器:
public class MyClassIdSerializer extends StdSerializer<MyClass> { public MyClassIdSerializer() { super(MyClass.class); } @Override public void serialize(MyClass value, JsonGenerator gen, SerializerProvider provider) throws IOException { // 直接输出对象的id值 gen.writeNumber(value.getId()); } }
- 在
MyClass上绑定这个序列化器:
// 移除原有的@JsonIdentityInfo注解,替换为序列化器配置 @JsonSerialize(using = MyClassIdSerializer.class) public class MyClass { private Long id; private String name; private LocalDate date; // getter/setter 方法... }
配置完成后,无论MyClass是首次出现还是重复引用,都会统一输出id数值,不会出现类型交替的情况。
场景2:始终输出完整对象(不使用ID引用)
如果希望每次都输出完整的MyClass对象,不需要ID引用优化,有两种实现方式:
方式一:直接移除@JsonIdentityInfo注解
最简单的处理方式就是删掉类上的@JsonIdentityInfo,Jackson会默认对每个对象进行完整序列化,不会用ID替代重复引用的对象。
方式二:全局配置ObjectMapper禁用对象引用处理
如果不想移除注解,也可以通过配置ObjectMapper来忽略@JsonIdentityInfo的ID引用逻辑:
ObjectMapper objectMapper = new ObjectMapper(); // 禁用对象引用的ID序列化/反序列化逻辑 objectMapper.disable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); objectMapper.disable(DeserializationFeature.USE_EQUALITY_FOR_OBJECT_ID);
这样即使保留@JsonIdentityInfo注解,Jackson也会跳过它的ID引用规则,每次都输出完整的对象内容。
另外补充:如果只是想针对某一次序列化临时修改行为,也可以动态配置:
// 单次序列化时禁用ID引用逻辑 String json = objectMapper.writer() .without(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID) .writeValueAsString(yourData);
内容的提问来源于stack exchange,提问作者AsconX
相关产品推荐
相关产品推荐

