Jackson如何仅序列化指定字段?解决ORM递归序列化问题
解决Jackson仅序列化指定字段+处理循环引用的方案
嘿,刚好处理过类似的场景,给你两个精准的解决方案,分别搞定「仅序列化指定字段」和「循环引用序列化」的问题:
一、仅序列化带有指定注解的字段
默认Jackson会序列化所有可访问的字段/getter方法,要实现默认忽略所有,只序列化带指定标记的字段,有两种常用方式:
方式1:使用@JsonView(推荐,代码侵入性低)
- 先定义一个标记用的空接口,用来区分需要序列化的字段:
public interface SerializeView {}
- 在你需要导出的字段(或对应的getter方法)上标注
@JsonView(SerializeView.class):
public class ExternalClass { // 这个字段会被序列化 @JsonView(SerializeView.class) private String neededField1; // 这个字段会被序列化 @JsonView(SerializeView.class) private Integer neededField2; // 其他大量字段默认被忽略 private String ignoreField1; private Long ignoreField2; // ... 更多无需导出的字段 }
- 序列化时指定使用这个View,同时关闭默认View包含规则:
ObjectMapper mapper = new ObjectMapper(); // 关键配置:只有标注了指定View的字段才会被序列化 mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); String json = mapper.writerWithView(SerializeView.class).writeValueAsString(externalObj);
方式2:使用@JsonProperty配合全局配置(更彻底)
如果你不想用View,也可以通过全局配置让Jackson默认忽略所有字段,只序列化带有@JsonProperty注解的字段:
ObjectMapper mapper = new ObjectMapper(); // 设置默认行为:仅序列化标注了@JsonProperty的字段 mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker() .withFieldVisibility(JsonAutoDetect.Visibility.NONE) .withGetterVisibility(JsonAutoDetect.Visibility.NONE) .withSetterVisibility(JsonAutoDetect.Visibility.NONE) .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
然后在需要序列化的字段上标注@JsonProperty即可:
public class ExternalClass { @JsonProperty private String neededField1; @JsonProperty private Integer neededField2; // 其他字段默认被忽略 }
二、解决ORM循环引用的序列化问题
对于A->B->A->B的递归关联,有三种常用解法:
方式1:@JsonManagedReference + @JsonBackReference(推荐双向关联场景)
在双向关联的两端分别标注这两个注解,主动端正常序列化,被动端被忽略:
public class ClassA { @JsonManagedReference // 主动关联端,正常序列化 private ClassB b; } public class ClassB { @JsonBackReference // 被动关联端,序列化时被忽略,避免循环 private ClassA a; }
方式2:@JsonIgnore(简单粗暴,单向忽略)
直接在导致循环的字段上标注@JsonIgnore,比如在ClassB的a字段上标注,这样序列化ClassA时不会递归序列化ClassB里的a:
public class ClassB { @JsonIgnore private ClassA a; }
方式3:@JsonIdentityInfo(保留关联关系,适合需要展示ID的场景)
如果需要保留对象的关联关系(比如序列化时用ID代替重复对象),可以用这个注解:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class ClassA { private Long id; private ClassB b; } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class ClassB { private Long id; private ClassA a; }
这样序列化时,第一次出现的对象会完整输出,后续重复出现的同一对象会用ID代替,既避免循环又保留了关联关系。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

