Jackson庫進行JSON?序列化時遇到了無限遞歸(Infinite?Recursion)的問題及解決方案
使用 Jackson 庫進行 JSON 序列化時遇到了 無限遞歸(Infinite Recursion) 問題,這是因為兩個實體類 ComPointQuotaEntity 和 ComPointEntity 之間存在雙向關聯(lián)(point 和 pointQuota 相互引用),導致序列化時陷入死循環(huán)。以下是解決方案:
解決方案
1. 使用 @JsonIgnore 忽略一個方向的引用
在其中一個實體類的關聯(lián)字段上添加 @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 替代直接序列化實體
創(chuàng)建 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 忽略循環(huán)引用
在 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. 自定義序列化器(高級)
為關聯(lián)字段自定義序列化邏輯,跳過循環(huán)引用:
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):簡單且能保持雙向關聯(lián)。
>- 推薦方案 3(DTO):徹底解耦序列化邏輯與數(shù)據(jù)庫實體,適合復雜場景。 - 避免直接序列化 JPA 實體,尤其是涉及雙向關聯(lián)時。
到此這篇關于Jackson庫進行JSON 序列化時遇到了 無限遞歸(Infinite Recursion)的問題及解決方案的文章就介紹到這了,更多相關Jackson JSON 序列化無限遞歸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- 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實現(xiàn)對象json之間的相互轉換(spring boot)
- 使用Jackson-json解析一個嵌套的json字符串
相關文章
Java class文件格式之方法_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了Java class文件格式之方法的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
springboot 使用yml配置文件自定義屬性的操作代碼
在SpringBoot中yml/yaml文件可以自定義一些屬性,以供注入給自定義bean對象的屬性,主要通過空格和層次來實現(xiàn),類似于python代碼,本文通過實例代碼給大家介紹springboot 使用yml配置文件自定義屬性,感興趣的朋友跟隨小編一起看看吧2024-03-03
java中線程的sleep()方法和yield()方法的區(qū)別
本文主要介紹了java中線程的sleep()方法和yield()方法的區(qū)別,Thread類的sleep()方法使線程休眠指定時間,不釋放鎖,而yield()提示調度器當前線程愿意讓出CPU資源,不保證立即切換線程,感興趣的可以了解一下2024-10-10
jenkins如何通過pipeline部署springboot項目
為了提高SpringBoot項目的部署效率和規(guī)范性,建議將項目代碼和部署腳本分離,項目代碼倉庫專注業(yè)務邏輯,構建為jar包;另外設立獨立代碼倉庫存放Jenkinsfile等部署配置文件,在Jenkins中配置pipeline,自動拉取項目代碼進行構建和部署2024-09-09
使用redisTemplate的scan方式刪除批量key問題
這篇文章主要介紹了使用redisTemplate的scan方式刪除批量key問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

