解決FastJson中"$ref重復(fù)引用"的問題方法
解決FastJson中"$ref重復(fù)引用"的問題,先來看一個(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對象的引用重復(fù)使用造成了重復(fù)引用問題,F(xiàn)astjson默認(rèn)開啟引用檢測將相同的對象寫成引用的形式:
{"$ref": "$"} // 引用根對象 {"$ref":"@"} // 引用自己 {"$ref":".."} // 引用父對象 {"$ref":"../.."} // 引用父對象的父對象 {"$ref":"$.members[0].reportTo"} // 基于路徑的引用
目前來說,前端還沒有一個(gè)很好的辦法來解析這樣的JSON格式。
除了上面的重復(fù)引用外, 還衍生出了另外一個(gè)概念:"循環(huán)引用",下面來看下兩者之間的區(qū)別吧:
- 重復(fù)引用:指一個(gè)對象引用重復(fù)出現(xiàn)多次
- 循環(huán)引用:對象A引用對象B,對象B引用對象A(這種情況一般是個(gè)雷區(qū),輕易不要嘗試的好,很容易引發(fā)StackOverflowError)
再來看一個(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引用檢測機(jī)制(慎用,循環(huán)引用時(shí)可能導(dǎo)致StackOverflowError)
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)
避免循環(huán)引用(某一方的引用字段不參與序列化:@JSONField(serialize=false))
避免一個(gè)對象引用被重復(fù)使用多次(使用拷貝的對象副本來完成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)); }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springboot實(shí)現(xiàn)在工具類(util)中調(diào)用注入service層方法
這篇文章主要介紹了springboot實(shí)現(xiàn)在工具類(util)中調(diào)用注入service層方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06springboot yml中profiles的巧妙用法(小白必看多環(huán)境配置)
這篇文章主要介紹了springboot yml中profiles的巧妙用法,非常適合多環(huán)境配置場景,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Java中Stream流中map和forEach的區(qū)別詳解
本文主要介紹了Java中Stream流中map和forEach的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04啟動(dòng)springboot應(yīng)用因未配置數(shù)據(jù)庫報(bào)錯(cuò)的解決方案
這篇文章主要介紹了啟動(dòng)springboot應(yīng)用因未配置數(shù)據(jù)庫報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Java經(jīng)典算法匯總之順序查找(Sequential Search)
Java查找算法之順序查找說明:順序查找適合于存儲(chǔ)結(jié)構(gòu)為順序存儲(chǔ)或鏈接存儲(chǔ)的線性表。 下面我們來詳細(xì)說明下2016-04-04Java使用list集合remove需要注意的事項(xiàng)(使用示例)
List集合的一個(gè)特點(diǎn)是它其中的元素是有序的,也就是說元素的下標(biāo)是根據(jù)插入的順序來的,在刪除頭部或者中間的一個(gè)元素后,后面的元素下標(biāo)會(huì)往前移動(dòng),本文給大家介紹Java使用list集合remove需要注意的事項(xiàng),感興趣的朋友一起看看吧2022-01-01SpringCloud?OpenFeign?服務(wù)調(diào)用傳遞?token的場景分析
這篇文章主要介紹了SpringCloud?OpenFeign?服務(wù)調(diào)用傳遞?token的場景分析,本篇文章簡單介紹?OpenFeign?調(diào)用傳遞?header?,以及多線程環(huán)境下可能會(huì)出現(xiàn)的問題,其中涉及到?ThreadLocal?的相關(guān)知識,需要的朋友可以參考下2022-07-07