Jackson庫(kù)進(jìn)行JSON?序列化時(shí)遇到了無(wú)限遞歸(Infinite?Recursion)的問(wèn)題及解決方案
使用 Jackson 庫(kù)進(jìn)行 JSON 序列化時(shí)遇到了 無(wú)限遞歸(Infinite Recursion) 問(wèn)題,這是因?yàn)閮蓚€(gè)實(shí)體類(lèi) ComPointQuotaEntity 和 ComPointEntity 之間存在雙向關(guān)聯(lián)(point 和 pointQuota 相互引用),導(dǎo)致序列化時(shí)陷入死循環(huán)。以下是解決方案:
解決方案
1. 使用 @JsonIgnore 忽略一個(gè)方向的引用
在其中一個(gè)實(shí)體類(lèi)的關(guān)聯(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
通過(guò)注解明確父子關(guān)系,Jackson 會(huì)序列化父級(jí)(@JsonManagedReference),但忽略子級(jí)(@JsonBackReference):
// ComPointQuotaEntity.java
public class ComPointQuotaEntity {
@ManyToOne
@JoinColumn(name = "point_id")
@JsonManagedReference // 標(biāo)記為父級(jí)(序列化)
private ComPointEntity point;
// 其他字段...
}
// ComPointEntity.java
public class ComPointEntity {
@OneToMany(mappedBy = "point")
@JsonBackReference // 標(biāo)記為子級(jí)(不序列化)
private List<ComPointQuotaEntity> pointQuota;
// 其他字段...
}3. 使用 DTO 替代直接序列化實(shí)體
創(chuàng)建 Data Transfer Object (DTO),只暴露需要的字段,避免直接序列化 JPA 實(shí)體:
// ComPointQuotaEntity.java
public class ComPointQuotaEntity {
@ManyToOne
@JoinColumn(name = "point_id")
@JsonManagedReference // 標(biāo)記為父級(jí)(序列化)
private ComPointEntity point;
// 其他字段...
}
// ComPointEntity.java
public class ComPointEntity {
@OneToMany(mappedBy = "point")
@JsonBackReference // 標(biāo)記為子級(jí)(不序列化)
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. 自定義序列化器(高級(jí))
為關(guān)聯(lián)字段自定義序列化邏輯,跳過(guò)循環(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());
// 僅序列化需要的字段,跳過(guò) pointQuota
gen.writeEndObject();
}
}
} 總結(jié)
- 推薦方案 2(@JsonManagedReference 和 @JsonBackReference):簡(jiǎn)單且能保持雙向關(guān)聯(lián)。
>- 推薦方案 3(DTO):徹底解耦序列化邏輯與數(shù)據(jù)庫(kù)實(shí)體,適合復(fù)雜場(chǎng)景。 - 避免直接序列化 JPA 實(shí)體,尤其是涉及雙向關(guān)聯(lián)時(shí)。
到此這篇關(guān)于Jackson庫(kù)進(jìn)行JSON 序列化時(shí)遇到了 無(wú)限遞歸(Infinite Recursion)的問(wèn)題及解決方案的文章就介紹到這了,更多相關(guān)Jackson JSON 序列化無(wú)限遞歸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Jackson使用示例-Bean、XML、Json之間相互轉(zhuǎn)換
- 一篇文章了解Jackson注解@JsonFormat及失效解決辦法
- Java中對(duì)象?和?json?互轉(zhuǎn)四種方式?json-lib、Gson、FastJson、Jackson
- 利用Jackson解決Json序列化和反序列化問(wèn)題
- Java利用Jackson輕松處理JSON序列化與反序列化
- Jackson中json格式的字符串與對(duì)象的互相轉(zhuǎn)換方式
- 如何自定義Jackson序列化?@JsonSerialize
- JSON中fastjson、jackson、gson如何選擇
- jackson 如何將實(shí)體轉(zhuǎn)json json字符串轉(zhuǎn)實(shí)體
- 使用jackson實(shí)現(xiàn)對(duì)象json之間的相互轉(zhuǎn)換(spring boot)
- 使用Jackson-json解析一個(gè)嵌套的json字符串
相關(guān)文章
Java實(shí)現(xiàn)mybatis批量插入數(shù)據(jù)到Oracle
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)mybatis批量插入數(shù)據(jù)到Oracle 的相關(guān)資料,需要的朋友可以參考下2016-06-06
java 通過(guò)cmd 調(diào)用命令啟動(dòng)tomcat的操作
這篇文章主要介紹了java 通過(guò)cmd 調(diào)用命令啟動(dòng)tomcat的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
idea每次新打開(kāi)的項(xiàng)目窗口maven都要重新設(shè)置問(wèn)題
這篇文章主要介紹了idea每次新打開(kāi)的項(xiàng)目窗口maven都要重新設(shè)置問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
java.lang.ExceptionInInitializerError初始化程序中的異常錯(cuò)誤的解決
java.lang.ExceptionInInitializerError?異常在?Java?中表示一個(gè)錯(cuò)誤,該錯(cuò)誤發(fā)生在嘗試初始化一個(gè)類(lèi)的靜態(tài)變量、靜態(tài)代碼塊或枚舉常量時(shí),本文就來(lái)介紹并解決一下,感興趣的可以了解一下2024-05-05
Spring Bean生命周期之BeanDefinition的合并過(guò)程詳解
這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之BeanDefinition的合并過(guò)程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
詳解Java實(shí)現(xiàn)簡(jiǎn)單SPI流程
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單SPI流程,SPI英文全稱(chēng)為Service Provider Interface,顧名思義,服務(wù)提供者接口,它是jdk提供給“服務(wù)提供廠商”或者“插件開(kāi)發(fā)者”使用的接口2023-03-03

