解決FastJson中"$ref重復(fù)引用"的問(wèn)題方法
解決FastJson中"$ref重復(fù)引用"的問(wèn)題,先來(lái)看一個(gè)例子吧:
public static void main(String[] args) {
UserGroup userGroup = new UserGroup().setName("UserGroup");
User user = new User("User");
for (int i = 0; i < 3; i++) {
userGroup.addUser(user);
}
Console.log(JSON.toJSONString(userGroup));
}
@Data
@AllArgsConstructor
static class User {
private String name;
}
@Data
@Accessors(chain = true)
static class UserGroup {
private String name;
private List<User> users = Lists.newArrayList();
public UserGroup addUser(User user) {
this.getUsers().add(user);
return this;
}
}
輸出結(jié)果:
{"name":"UserGroup","users":[{"name":"User"},{"$ref":"$.users[0]"},{"$ref":"$.users[0]"}]}
<!--- more --->
上面的現(xiàn)象就是將user對(duì)象的引用重復(fù)使用造成了重復(fù)引用問(wèn)題,F(xiàn)astjson默認(rèn)開(kāi)啟引用檢測(cè)將相同的對(duì)象寫(xiě)成引用的形式:
{"$ref": "$"} // 引用根對(duì)象
{"$ref":"@"} // 引用自己
{"$ref":".."} // 引用父對(duì)象
{"$ref":"../.."} // 引用父對(duì)象的父對(duì)象
{"$ref":"$.members[0].reportTo"} // 基于路徑的引用
目前來(lái)說(shuō),前端還沒(méi)有一個(gè)很好的辦法來(lái)解析這樣的JSON格式。
除了上面的重復(fù)引用外, 還衍生出了另外一個(gè)概念:"循環(huán)引用",下面來(lái)看下兩者之間的區(qū)別吧:
- 重復(fù)引用:指一個(gè)對(duì)象引用重復(fù)出現(xiàn)多次
- 循環(huán)引用:對(duì)象A引用對(duì)象B,對(duì)象B引用對(duì)象A(這種情況一般是個(gè)雷區(qū),輕易不要嘗試的好,很容易引發(fā)StackOverflowError)
再來(lái)看一個(gè)循環(huán)引用的例子:
public static void main(String[] args) {
Order order = new Order().setName("Order");
Item item = new Item().setName("Item");
item.setOrder(order);
order.setItem(item);
Console.log(JSON.toJSONString(order));
Console.log("----------------------------");
Console.log(JSON.toJSONString(item));
}
@Data
@Accessors(chain = true)
static class Order {
private String name;
private Item item;
}
@Data
@Accessors(chain = true)
static class Item {
private String name;
private Order order;
}
{"item":{"name":"Item","order":{"$ref":".."}},"name":"Order"}
----------------------------
{"name":"Item","order":{"item":{"$ref":".."},"name":"Order"}}
解決方案
關(guān)閉FastJson引用檢測(cè)機(jī)制(慎用,循環(huán)引用時(shí)可能導(dǎo)致StackOverflowError)
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)
避免循環(huán)引用(某一方的引用字段不參與序列化:@JSONField(serialize=false))
避免一個(gè)對(duì)象引用被重復(fù)使用多次(使用拷貝的對(duì)象副本來(lái)完成JSON數(shù)據(jù)填充)
public static void main(String[] args) {
UserGroup userGroup = new UserGroup().setName("UserGroup");
User user = new User("User");
for (int i = 0; i < 3; i++) {
User duplicateUser = new User();
BeanUtil.copyProperties(user, duplicateUser);
userGroup.addUser(duplicateUser);
}
Console.log(JSON.toJSONString(userGroup));
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot權(quán)限認(rèn)證-Sa-Token的使用詳解
Sa-Token是一款輕量級(jí)Java權(quán)限認(rèn)證框架,它簡(jiǎn)化了權(quán)限管理,提高了開(kāi)發(fā)效率,本文通過(guò)實(shí)例介紹了Sa-Token的基本概念、與其他框架的比較、基本語(yǔ)法和高級(jí)用法,并探討了其核心原理和實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友一起看看吧2024-09-09
java對(duì)象類(lèi)型轉(zhuǎn)換和多態(tài)性(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇java對(duì)象類(lèi)型轉(zhuǎn)換和多態(tài)性(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
Java synchronize底層實(shí)現(xiàn)原理及優(yōu)化
這篇文章主要介紹了Java synchronize底層實(shí)現(xiàn)原理及優(yōu)化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Spring?Cloud?Ribbon?中的?7?種負(fù)載均衡策略的實(shí)現(xiàn)方法
Ribbon?內(nèi)置了?7?種負(fù)載均衡策略:輪詢策略、權(quán)重策略、隨機(jī)策略、最小連接數(shù)策略、重試策略、可用性敏感策略、區(qū)域性敏感策略,并且用戶可以通過(guò)繼承?RoundRibbonRule?來(lái)實(shí)現(xiàn)自定義負(fù)載均衡策略,對(duì)Spring?Cloud?Ribbon負(fù)載均衡策略相關(guān)知識(shí)感興趣的朋友一起看看吧2022-03-03
Java 中如何使用 JavaFx 庫(kù)標(biāo)注文本顏色
這篇文章主要介紹了在 Java 中用 JavaFx 庫(kù)標(biāo)注文本顏色,在本文中,我們將了解如何更改標(biāo)簽的文本顏色,并且我們還將看到一個(gè)必要的示例和適當(dāng)?shù)慕忉專员愀菀桌斫庠撝黝},需要的朋友可以參考下2023-05-05
SpringBoot+Apache tika實(shí)現(xiàn)文檔內(nèi)容解析的示例詳解
Apache tika是Apache開(kāi)源的一個(gè)文檔解析工具,本文主要為大家介紹了如何在springboot中引入tika的方式解析文檔,感興趣的小伙伴可以了解一下2023-07-07

