Springboot中JSON序列化无限递归(StackOverflowError)问题求助
解决JPA一对多关联JSON无限递归的方案
出现Could not write JSON: Infinite recursion (StackOverflowError)的核心原因是实体类双向引用导致JSON序列化时无限循环:NPMCore包含NPMFinition集合,NPMFinition又持有NPMCore的引用,序列化引擎会不断在两个对象间来回解析,最终触发栈溢出。
以下是几种实用的解决方案:
1. 使用Jackson双向引用注解(推荐)
通过@JsonManagedReference和@JsonBackReference标记主动/被动引用,序列化时自动忽略被动引用的解析:
// NPMCore 实体类 public class NPMCore { // 主键及其他业务字段 @OneToMany(mappedBy = "npmCore") @JsonManagedReference // 标记主动引用,正常序列化集合 private List<NPMFinition> npmFinitions; // getter、setter 方法 } // NPMFinition 实体类 public class NPMFinition { // 主键及其他业务字段 @ManyToOne @JsonBackReference // 标记被动引用,序列化时忽略该字段 private NPMCore npmCore; // getter、setter 方法 }
2. 直接忽略关联字段
如果返回的JSON不需要包含反向关联的NPMCore实例,可以用@JsonIgnore直接标记忽略该字段:
// NPMFinition 实体类 public class NPMFinition { @ManyToOne @JsonIgnore // 序列化时完全忽略该关联字段 private NPMCore npmCore; // 其他字段及方法 }
注意:该注解会同时影响序列化和反序列化,如果有需要从JSON反序列化NPMFinition的场景,需谨慎使用。
3. 自定义DTO(数据传输对象)
创建仅包含前端需要字段的DTO类,避免直接序列化实体类,从根源切断循环引用:
// NPMCoreDTO 仅保留需要返回的业务字段 public class NPMCoreDTO { private Long id; private String coreName; // 替换为实际业务字段 private List<NPMFinitionDTO> npmFinitions; // 构造方法、getter、setter } // NPMFinitionDTO 不包含NPMCore引用 public class NPMFinitionDTO { private Long id; private String finitionDetail; // 替换为实际业务字段 // 构造方法、getter、setter }
在接口中查询到实体后,将实体转换为DTO再返回(可手动转换或使用MapStruct等工具简化操作)。
4. 使用对象标识注解
通过@JsonIdentityInfo给实体分配唯一ID,重复引用时仅输出ID而非完整对象:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class NPMCore { @Id private Long id; @OneToMany(mappedBy = "npmCore") private List<NPMFinition> npmFinitions; // 其他内容 } @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class NPMFinition { @Id private Long id; @ManyToOne private NPMCore npmCore; // 其他内容 }
这种方式会在第一次序列化对象时输出完整内容,后续重复引用时仅输出对象的ID值。
内容的提问来源于stack exchange,提问作者Lisa Juliette
相关产品推荐
相关产品推荐

