Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案
使用 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 序列化无限递归内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
- Jackson使用示例-Bean、XML、Json之间相互转换
- 一篇文章了解Jackson注解@JsonFormat及失效解决办法
- Java中对象 和 json 互转四种方式 json-lib、Gson、FastJson、Jackson
- 利用Jackson解决Json序列化和反序列化问题
- Java利用Jackson轻松处理JSON序列化与反序列化
- Jackson中json格式的字符串与对象的互相转换方式
- 如何自定义Jackson序列化 @JsonSerialize
- JSON中fastjson、jackson、gson如何选择
- jackson 如何将实体转json json字符串转实体
- 使用jackson实现对象json之间的相互转换(spring boot)
- 使用Jackson-json解析一个嵌套的json字符串
相关文章
Java class文件格式之方法_动力节点Java学院整理
这篇文章主要为大家详细介绍了Java class文件格式之方法的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-06-06
springboot 使用yml配置文件自定义属性的操作代码
在SpringBoot中yml/yaml文件可以自定义一些属性,以供注入给自定义bean对象的属性,主要通过空格和层次来实现,类似于python代码,本文通过实例代码给大家介绍springboot 使用yml配置文件自定义属性,感兴趣的朋友跟随小编一起看看吧2024-03-03
java中线程的sleep()方法和yield()方法的区别
本文主要介绍了java中线程的sleep()方法和yield()方法的区别,Thread类的sleep()方法使线程休眠指定时间,不释放锁,而yield()提示调度器当前线程愿意让出CPU资源,不保证立即切换线程,感兴趣的可以了解一下2024-10-10
jenkins如何通过pipeline部署springboot项目
为了提高SpringBoot项目的部署效率和规范性,建议将项目代码和部署脚本分离,项目代码仓库专注业务逻辑,构建为jar包;另外设立独立代码仓库存放Jenkinsfile等部署配置文件,在Jenkins中配置pipeline,自动拉取项目代码进行构建和部署2024-09-09
使用redisTemplate的scan方式删除批量key问题
这篇文章主要介绍了使用redisTemplate的scan方式删除批量key问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2023-12-12


最新评论