对象转 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

GSON 循环引用的对象转为 JSON 造成栈溢出相关推荐

  1. java-利用反射做一个将javabean对象转为json的小工具(v1)

    java-利用反射做一个将javabean对象转为json字符串的小工具(v1) 解决思路 1 利用反射机制获取对象的所有字段 2 遍历,将字段名和值按照一定格式添加到字符串中 所需知识 1 反射基础 ...

  2. 【Groovy】json 序列化 ( 类对象转为 json 字符串 | 使用 JsonBuilder 进行转换 | 使用 JsonOutput 进行转换 | 将 json 字符串格式化输出 )

    文章目录 一.Groovy 对象转为 json 字符串 ( 使用 JsonBuilder 进行转换 ) 二.使用 JsonOutput 将指定类型对象转为 json 字符串 三.将 json 字符串格 ...

  3. Gson案例:Java对象与JSON字符串相互转换

    Gson案例:Java对象与JSON字符串相互转换 一.Gson概述 Gson是一个Java类库,可将Java对象转换为相应的JSON形式,也可以将JSON字符串转换为对应的Java对象.Gson是一 ...

  4. js字符串转换为json对象JSON.parse()及将json对象转为json字符串JSON.stringify()

    一.JSON对象中有两个非常好用的方法: 1 JSON.stringify接收一个JS对象转化为json字符串 2 JSON.parse接受json字符串转化为JS对象 const my={ name ...

  5. ObjectMapper实现将Java对象转为json字符串

    ObjectMapper调用 添加pom依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId>&l ...

  6. 多数组对象转为json数组格式

    JS多数组对象转为json数组 在工作中经常会遇到接口获取的数据结构与需要的数据结构不同的情况,这就需要我们自己把接口数据改为我们需要的格式. 情况一: var resData = {datetime ...

  7. python 引用计数 循环引用_Python对象的循环引用问题

    Python对象循环引用 我们来介绍一下 Python 是采用何种途径解决循环引用问题的. 循环引用垃圾回收算法 上图中,表示的是对象之间的引用关系,从自对象指向他对象的引用用黑色箭头表示.每个对象里 ...

  8. 记录如何深度拷贝一个属性存在循环引用的对象

    深度拷贝的实现思路是遍历对象的 property 取值然后进行递归调用.(代码部分假设该对象的属性均为 object) function fn(object) {for (var key in obj ...

  9. java解析与生成json数据的四种方式,比如将json字符串转为json对象或json对象转为json字符串

    文章目录 1. 详说json 1.1 何为json 1.2 json语法 2. Java解析与生成JSON的四种方式 2.1 传统方式 2.2 利用Jackson方式 2.3 利用Gson方式 2.4 ...

最新文章

  1. 交通部:将从五方面推进京津冀暨雄安新区交通建设
  2. phpcms调用栏目描述_phpcms v9栏目列表调用每一篇文章内容方法
  3. make_heap(),push_heap(),pop_heap(),sort_heap()用法。
  4. 《大数据》2021年第4期目次摘要
  5. php判断汉字是否相等,JavaScript
  6. 最新pvz服务器补偿码,阴阳师:补偿来了!大量活动导致服务器崩溃,现已修复且下发补偿...
  7. 如何实现一个php框架系列文章【2】实现类的自动加载
  8. html meta标签
  9. 接口自动化-get/post接口详解
  10. 计算机word图表布布局在哪,word中的页面布局在哪里
  11. 【码农说码】手撕锟斤拷,彻底搞懂GB2312,GBK,Big5,ASCII,UTF-8,UTF-32的前世今生
  12. 徐直军、何小鹏等大咖加盟,2021互联网岳麓峰会即将重磅开幕
  13. 04.HTML基础-表单标签基础标签
  14. 利用Python+OpenCV对图像加密/解密
  15. SIR传染模型Matlab代码,sir传染病模型 MATLAB代码运行不了,
  16. 修复打开Excel提示
  17. 获取上一个交易日—python
  18. 矩阵的最小路径和(Java)
  19. iSpring Suite教程:使用iSpring创建视频讲座只需简单6步(上)
  20. Minecraft TrMenu 菜单插件 研究心得

热门文章

  1. CIKM 2021 | AMTL:设计孪生掩码层高效学习维度自适应的Embedding
  2. Linux串口编程_termios
  3. mysql 锁怎么使用_Mysql锁一般使用
  4. 上传到服务器gd不支持,安装dedecms出现GD不支持。我的php5.5的。怎么解决?
  5. java 多线程异常_java多线程执行异常
  6. python去重且顺序不变_Python中list去重且保持原顺序不变的方法
  7. MySQL explain结果详解
  8. 感知算法论文(二)Pelee: A Real-Time Object Detection System on Mobile Devices(2018)译文
  9. 随机森林算法的随机性_理解随机森林算法的图形指南
  10. 深入浅出SQL(三)——表的规范化