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.mzph.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…