Java Fasterxml下互相依赖JsonObject的序列化反序列化问题求解
解决方案
Jackson(即你使用的fasterxml序列化库)已经内置了处理双向循环引用的原生功能,无需自行维护ID或编写后置加载逻辑,目前有两种常用方案可按需选择:
方案1:@JsonManagedReference + @JsonBackReference
适合不需要在JSON中显式输出反向引用的场景,仅需在对应字段加注解即可:
- 主引用侧(你需要完整序列化输出的一侧,这里是Plot类的合同列表字段)加
@JsonManagedReference - 反向引用侧(PurchaseContract类的关联Plot字段)加
@JsonBackReference
示例代码:
public class Plot { private Long id; private String plotCode; // 主引用侧注解 @JsonManagedReference private List<PurchaseContract> purchaseContracts; // 省略getter、setter、构造方法 } public class PurchaseContract { private Long id; private String contractCode; // 反向引用侧注解 @JsonBackReference private Plot relatedPlot; // 省略getter、setter、构造方法 }
该方案特性:序列化时仅会输出Plot下的合同列表内容,PurchaseContract的relatedPlot字段不会写入JSON;反序列化时Jackson会自动填充反向引用的对象,不会出现重复实例或循环报错问题。
方案2:@JsonIdentityInfo
适合需要双向序列化输出的场景,比如单独序列化PurchaseContract时也需要展示关联的Plot信息,仅需在类上添加注解即可:
// 用类自带的id属性作为唯一标识 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Plot { private Long id; private String plotCode; private List<PurchaseContract> purchaseContracts; // 省略getter、setter、构造方法 } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class PurchaseContract { private Long id; private String contractCode; private Plot relatedPlot; // 省略getter、setter、构造方法 }
如果类本身没有内置唯一ID字段,也可以使用Jackson提供的自动生成器:
@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class)
该方案特性:序列化时首次出现的对象会输出完整内容,后续同一个对象再次被引用时仅会输出对应的唯一标识;反序列化时Jackson会自动将相同标识的引用指向同一个实例,彻底解决重复创建和循环依赖报错问题。
注意事项
两种方案均为Jackson原生功能,无需引入额外依赖,仅需添加注解即可,不会侵入业务逻辑代码。
内容的提问来源于stack exchange,提问作者blafexe
相关产品推荐
相关产品推荐

