本文主要是介绍Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursion)的问题及解决方案》使用Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursi...
使用 Jackson 库进行 JSON 序列化时遇到了 无限递归(Infinite Recursion) 问题,这是因为两个实体类 ComPointQuotaEntity 和 ComPointEntity 之间存在双向关联(point 和 pointQuota 相互引用),导致序列化时陷入死循环。以下是解决方案:
解决方案
1. 使用 @JsonIgnore 忽略一个方向的引用
在其中一个实体类的关联字段上添加 @JsonIgnore
注解,直接阻止某一方的序列化:
// ComPointQuotaEntity.Java public class ComPointQuotaEntity { @ManyToOne @JoinColumn(name = "point_id") private ComPointEntity point; // 保留此字段的序列化 // 其他字段... } // ComPointEntity.java public class ComPointEntity { @OneToMany(mappedBy = "point") @JsonIgnore // 忽略此字段的序列化 private List<ComPointQuotaEntity> pointQuota; // 其他字段.China编程.. }
2. 使用 @JsonManagedReference 和 @JsonBackReference
通过注解明确父子关系,javascriptJackson 会序列化父级(@JsonManagedReference
),但忽略子级(@JsonBackReference
):
// ComPointQuotaEntity.java public class ComPointQuotaEntity { @ManyToOne @JoinColumn(name = "point_id") @JsonManagedReference // 标记为父级(序列化) private ComPointEntity point; // 其他字段... } // ComPointEntity.java public class ComPointEntity { @OneToMany(mappedBy = "point") @JsonBackReference // 标记为子级(不序列化) private List<ComPointQuotaEntijsty> pointQuota; // 其他字段... }
3. 使用 DTO 替代直接序列化实体
创建 Data Transfer Object (DTO),只暴露需要的字段,避免直接序列化 JPA 实体:
// ComPointQuotaEntity.java public class ComPointQuotaEntity { @ManyToOne @JoinColumwww.chinasem.cnn(name = "point_id") @JsonManagedReference // 标记为父级(序列化) private ComPointEntity point; // 其他字段... } // ComPointEntity.java public class ComPointEntity { @OneToMany(mappedBy = "point") @JsonBackReference // 标记为子级(不序列化) private List<ComPointQuotaEntity> pointQuota; // 其他字段... }
4. 配置 Jackson 忽略循环引用
在 application.properties 或 application.yml 中配置 Jackson:
# application.properties spring.jackson.serialization.fail-on-emptandroidy-beans=false spring.jackson.serialization.fail-on-self-references=false
或在代码中配置 ObjectMapper:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper() .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) .configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false); } }
5. 自定义序列化器(高级)
为关联字段自定义序列化逻辑,跳过循环引用:
public class ComPointQuotaEntity { @ManyToOne @JoinColumn(name = "point_id") @JsonSerialize(using = ComPointEntitySerializer.class) private ComPointEntity point; // 其他字段... } public class ComPointEntitySerializer extends JsonSerializer<ComPointEntity> { @Override public void serialize(ComPointEntity value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (value != null) { gen.writeStartObject(); gen.writeNumberField("id", value.getId()); // 仅序列化需要的字段,跳过 pointQuota gen.writeEndObject(); } } }
总结
- 推荐方案 2(@JsonManagedReference 和 @JsonBackReference):简单且能保持双向关联。
>- 推荐方案 3(DTO):彻底解耦序列化逻辑与数据库实体,适合复杂场景。 - 避免直接序列化 JPA 实体,尤其是涉及双向关联时。
到此这篇关于Jackson库进行JSON 序列化时遇到了 无限递归(Infinite Recursion)的问题及解决方案的文章就介绍到这了,更多相关Jackson JSON 序列化无限递归内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!