使用 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;
// 其他字段...
}2. 使用 @jsonmanagedreference 和 @jsonbackreference
通过注解明确父子关系,jackson 会序列化父级(@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<compointquotaentity> pointquota;
// 其他字段...
}3. 使用 dto 替代直接序列化实体
创建 data transfer object (dto),只暴露需要的字段,避免直接序列化 jpa 实体:
// 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<compointquotaentity> pointquota;
// 其他字段...
}4. 配置 jackson 忽略循环引用
在 application.properties 或 application.yml 中配置 jackson:
# application.properties spring.jackson.serialization.fail-on-empty-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 序列化无限递归内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论