javascript
GSON 循环引用的对象转为 JSON 造成栈溢出
對象轉(zhuǎn) JSON 可能引發(fā)棧溢出的異常,一般是因為對象中的循環(huán)引用引起不斷遞歸。
常見的作法就是:
- 換一種 JSON 的序列化工具,比如?fastjson 默認(rèn)支持消除對同一對象循環(huán)引用
- transient 修飾屬性
- 顯式排除對象的某些屬性
?
1. java對象引用成環(huán)說明
1.1 相互引用成環(huán):
class A{B b;}class B{A a;}?
1.2 自引用成環(huán):
class A{A a;}2. 引用成環(huán)造成的問題
在java中,對象引用成環(huán)問題,可以被jvm自動處理,但是將java對象轉(zhuǎn)成json格式時,由于轉(zhuǎn)換工具不能自行切斷環(huán),會導(dǎo)致無限解析最終會導(dǎo)致棧溢出錯誤。
?
3. 解決方法:
?所有解決方法,基本原理都是將“環(huán)”切斷。
1)gson提供了非常簡潔的處理方式,將所有要轉(zhuǎn)換成json的變量都用@Expose注解標(biāo)記;將出現(xiàn)環(huán)的地方,不做任何處理。
2)創(chuàng)建gson構(gòu)造器:
?
// 獲取Gson構(gòu)造器,可以過濾掉不帶注解的字段 Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();?
?
3)轉(zhuǎn)換json:
?
gson.toJson(testOject);?
使用上面第一個相互引用成環(huán)的例子舉例說明:
3.1 阻斷環(huán)路:
?
class A{@ExposeB b; }class B{A a;//不轉(zhuǎn)換該字段,阻斷循環(huán)引用 }?
3.2 創(chuàng)建gson構(gòu)造器,并轉(zhuǎn)換json:
?
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();// 獲取Gson構(gòu)造器,可以過濾掉不帶注解的字段 A testObj = new A();String json = gson.toJson(testObj);//獲取json數(shù)據(jù)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
?
轉(zhuǎn)載于:https://www.cnblogs.com/tuhooo/p/11163070.html
總結(jié)
以上是生活随笔為你收集整理的GSON 循环引用的对象转为 JSON 造成栈溢出的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 建行如何开通网上银行?开通步骤看这里!
- 下一篇: 广发银行信用卡制卡要多久能到?卡片要审核