GSON 循環引用的對象轉為 JSON 造成棧溢出

對象轉 JSON 可能引發棧溢出的異常,一般是因為對象中的循環引用引起不斷遞歸。

常見的作法就是:

  • 換一種 JSON 的序列化工具,比如?fastjson 默認支持消除對同一對象循環引用
  • transient 修飾屬性
  • 顯式排除對象的某些屬性

?

1. java對象引用成環說明

1.1 相互引用成環:

class A{B b;}class B{A a;}

?

1.2 自引用成環:

class A{A a;}

2. 引用成環造成的問題

在java中,對象引用成環問題,可以被jvm自動處理,但是將java對象轉成json格式時,由于轉換工具不能自行切斷環,會導致無限解析最終會導致棧溢出錯誤。

?

3. 解決方法:

?所有解決方法,基本原理都是將“環”切斷。

1)gson提供了非常簡潔的處理方式,將所有要轉換成json的變量都用@Expose注解標記;將出現環的地方,不做任何處理。

2)創建gson構造器:

?

// 獲取Gson構造器,可以過濾掉不帶注解的字段
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

?

?

3)轉換json:

?

gson.toJson(testOject);

?

使用上面第一個相互引用成環的例子舉例說明:

3.1 阻斷環路:

?

class A{@ExposeB b;
}class B{A a;//不轉換該字段,阻斷循環引用

}

?

3.2 創建gson構造器,并轉換json:

?

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();// 獲取Gson構造器,可以過濾掉不帶注解的字段

A testObj = new A();String json = gson.toJson(testObj);//獲取json數據

Gson 官方文檔

Excluding Fields From Serialization and Deserialization

Gson supports numerous mechanisms for excluding top-level classes, fields and field types. Below are pluggable mechanisms that allow field and class exclusion. If none of the below mechanisms satisfy your needs then you can always use?custom serializers and deserializers.

Java Modifier Exclusion

By default, if you mark a field as?transient, it will be excluded. As well, if a field is marked as?static?then by default it will be excluded. If you want to include some transient fields then you can do the following:

import java.lang.reflect.Modifier;

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.STATIC).create();

?

NOTE: you can give any number of the?Modifier?constants to the?excludeFieldsWithModifiers?method. For example:

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE).create();

?

Gson's?@Expose

This feature provides a way where you can mark certain fields of your objects to be excluded for consideration for serialization and deserialization to JSON. To use this annotation, you must create Gson by using?new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(). The Gson instance created will exclude all fields in a class that are not marked with?@Expose?annotation.

User Defined Exclusion Strategies

If the above mechanisms for excluding fields and class type do not work for you then you can always write your own exclusion strategy and plug it into Gson. See the?ExclusionStrategy?JavaDoc for more information.

The following example shows how to exclude fields marked with a specific?@Foo?annotation and excludes top-level types (or declared field type) of class?String.

@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})public @interface Foo {// Field tag only annotation

}public class SampleObjectForTest {@Foo private final int annotatedField;private final String stringField;private final long longField;private final Class<?> clazzField;public SampleObjectForTest() {annotatedField = 5;stringField = "someDefaultValue";longField = 1234;}}public class MyExclusionStrategy implements ExclusionStrategy {private final Class<?> typeToSkip;private MyExclusionStrategy(Class<?> typeToSkip) {this.typeToSkip = typeToSkip;}public boolean shouldSkipClass(Class<?> clazz) {return (clazz == typeToSkip);}public boolean shouldSkipField(FieldAttributes f) {return f.getAnnotation(Foo.class) != null;}}public static void main(String[] args) {Gson gson = new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy(String.class)).serializeNulls().create();SampleObjectForTest src = new SampleObjectForTest();String json = gson.toJson(src);System.out.println(json);}

?

The output is:

{"longField":1234}

?

?

References

https://blog.csdn.net/weixin_33712987/article/details/87500527

https://my.oschina.net/airship/blog/792414

https://github.com/google/gson/blob/master/UserGuide.md#TOC-Excluding-Fields-From-Serialization-and-Deserialization

?

轉載于:https://www.cnblogs.com/tuhooo/p/11163070.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247564.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247564.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247564.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一些雜七雜八的前端知識1

一、this指向 this是函數運行時自動生成的一個內部對象&#xff0c;只能在函數內部使用 1. 指向全局變量 純粹的函數調用 2. 作為對象方法的調用 對象調用某個函數&#xff0c;這個函數里面所包含的this也就指向使用這個函數的對象了 3. 函數構造新對象時調用 new 4. a…

最新的vue webpack模板沒有dev-server.js文件,進行后臺數據模擬筆記

最新的vue里dev-server.js被替換成了webpack-dev-conf.js 在模擬后臺數據的時候直接在webpack-dev-conf.js文件中修改 第一步&#xff0c;在const portfinder require(‘portfinder’)后添加//第一步 const express require(express) const app express()//請求server var a…

20080331 - What is a PID, How is it useful when troubleshooting a system

PID Process Identifier, 是一個全局唯一的用來標識進程的整數。在多任務系統中&#xff0c;可用來診斷系統中發生錯誤的進程。 轉載于:https://www.cnblogs.com/likun/archive/2008/03/31/1130458.html

記一次el-input使用的坑

記一次el-input使用的坑 el-input使用不同與原生input&#xff0c;所以在vue中改變綁定的數據時需注意 <el-input v-model"form.schedule" input"validateNumber($event)" />要想在input時改變form.schedule的值來改變輸入框顯示的值&#xff0c;以…

使用pm2啟動Node和Vue項目教程

安裝pm2 $ npm install -g pm2 命令行全局安裝pm2 將pm2加入到命令中去?1234ln -s /usr/local/src/node-v8.9.1-linux-x64/bin/pm2 /usr/local/bin/pm2ln -s /usr/local/src/node-v8.9.1-linux-x64/bin/pm2-dev /usr/local/bin/pm2-devln -s /usr/local/src/node-v8.9.1-lin…

對正則的研究

視頻鏈接地址&#xff08;視頻格式可按需增刪&#xff09; /^https?:\/\/.*?(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|mp4)$/i 圖片鏈接地址&#xff08;圖片格式可按需增刪&#xff09; /^https?:\/\/.*?(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif)$/i 24小時制時間&a…

MVVM原理還你

眾所周知當下是MVVM盛行的時代&#xff0c;從早期的Angular到現在的React和Vue&#xff0c;再從最初的三分天下到現在的兩虎相爭。 無疑不給我們的開發帶來了一種前所未有的新體驗&#xff0c;告別了操作DOM的思維&#xff0c;換上了數據驅動頁面的思想&#xff0c;果然時代的進…

poj1316

1&#xff0e;鏈接地址 https://vjudge.net/problem/POJ-1316 2&#xff0e;問題描述 In 1949 the Indian mathematician D.R. Kaprekar discovered a class of numbers called self-numbers. For any positive integer n, define d(n) to be n plus the sum of the digits of …

CSS頁面布局解決方案大全

前端布局非常重要的一環就是頁面框架的搭建&#xff0c;也是最基礎的一環。在頁面框架的搭建之中&#xff0c;又有居中布局、多列布局以及全局布局&#xff0c;今天我們就來總結總結前端干貨中的CSS布局。 居中布局 水平居中 1&#xff09;使用inline-blocktext-align&#xff…

AES加密算法的學習筆記

AES簡介高級加密標準(AES,Advanced Encryption Standard)為最常見的對稱加密算法(微信小程序加密傳輸就是用這個加密算法的)。 對稱加密算法也就是加密和解密用相同的密鑰&#xff0c;具體的加密流程如下圖&#xff1a; 下面簡單介紹下各個部分的作用與意義&#xff1a; 明文P沒…

為什么要用setTimeout模擬setInterval ?

setInterval有兩個缺點&#xff1a; 使用setInterval時&#xff0c;某些間隔會被跳過&#xff1b;可能多個定時器會連續執行&#xff1b;在前一個定時器執行完前&#xff0c;不會向隊列插入新的定時器&#xff08;解決缺點一&#xff09;保證定時器間隔&#xff08;解決缺點二&…

前端 crypto-js aes 加解密

背景 前段時間公司做項目&#xff0c;該項目涉及到的敏感數據比較多&#xff0c;經過的一波討論之后&#xff0c;決定前后端進行接口加密處理&#xff0c;采用的是 AES BASE64 算法加密~ 網上關于 AES 對稱加密的算法介紹看上一篇&#xff01; 具體實現 其實搞懂了是怎么一回事…

對排序算法的研究

算法是什么&#xff1f;、 算法&#xff08;Algorithm&#xff09; 代表著用系統的方法描述解決問題的策略機制&#xff0c;可以通過一定規范的 輸入&#xff0c;在有限時間內獲得所需要的 輸出。 一個算法的好壞是通過 時間復雜度 與 空間復雜度 來衡量的。 簡單來說&#xff…

js實用算法

判斷文本是否為回文 定義&#xff1a;如果將一個文本翻轉過來&#xff0c;能和原文本完全相等&#xff0c;那么就可以稱之為“回文”。 方法一&#xff08;字符串、數組內置方法&#xff09;123456789101112131415/** 判斷文字是否為回文* param {string|number} val 需要判斷的…

stylus

stylus格式 指將css中{} &#xff1b;去掉即可

隨筆記錄(2019.7.10)

1、ISO/OSI 網絡七層參考模型 物理層 數據鏈路層 網絡層 傳輸層 會話層 表示層 應用層 2、 TCP/IP 網絡四層模型和五層模型 四層模型&#xff1a; 網絡接口層 網絡層 傳輸層 應用層 五層模型&#xff1a; 物理層 數據鏈路層 網絡層 傳輸層 應用層 3、 協議簇 &#xff08;1&a…

轉發:Ajax動態畫EChart圖表

本人由于項目需要&#xff0c;在狀態變化的時候需要動態繪制對應數據的EChart圖表&#xff0c;并且不刷新整個網頁。 所以就用Ajax動態畫EChart圖表&#xff0c;下面是開發過程中遇到的一些坑的總結。 流程&#xff1a;頁面首次加載時展示一幅原始的圖形&#xff0c;若后臺數據…

如果硬盤不顯示可以這么處理

http://www.zhuangjiba.com/soft/9574.html轉載于:https://www.cnblogs.com/braveheart007/p/11167311.html

Highcharts的餅圖大小的控制

在Highcharts中&#xff0c;餅圖的大小是Highcharts自動計算并進行繪制。餅圖的大小受數據標簽大小、數據標簽到切片的距離影響。當數據標簽內容較多&#xff0c;并且距離切片較遠時&#xff0c;餅圖就會被壓縮的很小。解決這個問題&#xff0c;有以下幾種方法&#xff1a;&…

轉:谷歌離線地圖基礎

一.需要文件 gapi3文件夾&#xff1a;存放接口等tilemap文件夾&#xff1a;存放圖片gapi.js文件maptool.js文件 二.html配置 <script type"text/javascript" src"gapi.js"></script> <script type"text/javascript" src"map…