一、现象:

项目中用json形式来存储一个集合对象,用fastjson发现多了一些东西:$ref,了解之后才发现是重复引用的问题。

[{"id":"1","orderList":[{"id":2,"date":"2020-08-17 12:57:21","name":"帽子"},{"id":3,"date":"2020-08-17 12:57:21","name":"鞋子"}],"remarks":""},{"id":"2","orderList":[{"$ref":"$[0].orderList[0]"},{"$ref":"$[0].orderList[1]"}],"remarks":"111"},
]

二、问题分析:$ref

  • 接口返回的api通过fastjson将实体转化为json字符串时,在传输的数据中如果出现相同的对象,fastjson默认开启引用检测会将相同的对象写成引用的形式
  • 引用是通过"$ref"来表示的
  • 引用分两种,循环引用和重复引用
引用 描述
"$ref":".." 上一级
"$ref":"@" 当前对象,也就是自引用
"$ref":"$" 根对象
"$ref":"$.children.0" 基于路径的引用,相当于 root.getChildren().get(0)

三、循环引用和重复引用

  1. 循环引用:即A对象引用B对象,B对象又引用A对象,这种情况是要极力避免的,因为会导致堆栈溢出(StackOverflowError);
  2. 重复引用:上面的例子就是因为相同的订单对象出现在两个集合中,所以第二个orderList集合中直接返回的是$ref。一般大家在写代码的过程中,如果出现$ref,通常应该是重复引用问题。

四、$ref问题的解决

网上能找到的解决方案有:

1.局部关闭

将该对象在后端转换为json字符串返回给前端,使用SerializerFeature.DisableCircularReferenceDetect关闭循环引用。

String jsonString=JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect);

正常来说,我们的接口返回给前端的是List<Object>这种格式,如果采用这个方式,就要将返回值改为String,不优雅。当然也可以把这个字符串再次转换为对象,这样循环引用的问题就没有了。

2.全局配置关闭

可以在SpringBoot项目的json配置中将循环引用关闭。FastJson的.java配置增加以下项:

fastConverter.setFeatures(SerializerFeature.DisableCircularReferenceDetect);

但是因为全局配置是在我们项目的基础jar包中配置的,改动基础jar包会有风险,会对前面所有的依赖项目产生影响。所以也不采用这种方式。

大家想想为什么fastjson默认是开启这个功能的就知道原因了。如果全局关闭,性能也会有极大影响。

3.new新的对象来避免

我们可以将List中的对象使用BeanUtil这样的工具,拷贝为新的对象,然后放到新的集合中返回。

   List<Object> orderListNew = new ArrayList<>();orderList.forEach(i->{Order target=new Order();BeanUtils.copyProperties(i,target);orderListNew.add(target);});return orderListNew;

BeanUtil创建出来的对象跟原来的对象不是同一个对象。需要额外的代码,有点丑。

4.禁止序列化

如果循环引用的数据,前端用不到,那可以在实体类对应的字段加注解禁止序列化,这样前端就不会接收到这个字段的引用数据了。

    @JSONField(serialize = false)private List<Order> orderList;

这样在转换的时候,orderList就不会被转换了。

5.在该字段的注解上指定序列化时关闭循环引用

但是很多时候,我们又需要这个数据,所以禁止序列化也是不行滴,接下来看另外一种注解解决方式。

    @JSONField(serialzeFeatures = {SerializerFeature.DisableCircularReferenceDetect})private List<Object> objectList;

此种方法才是我项目中的解决办法。

参考资料:

  1. https://blog.csdn.net/fly910905/article/details/81504388

解决FastJson中“$ref 循环引用检测”的问题的几种方式相关推荐

  1. 【FastJSON】解决FastJson中“$ref 循环引用”的问题

    0.开发环境 SSH,EasyUI,MySQL 1.需求要求: (1)首先获取所有的贷款订单数据,即List <LoanOrder>. (2)然后从单个贷款订单实体LoanOrder去访问 ...

  2. 解决用户控件循环引用的笨办法

    在上一篇中提到使用MagicAjax开发了一个项目,因为做这个项目之前对MagicAjax不是很了解,在里面使用了用户控件,我发现这是一个很致命的错误,用户控件在MagicAjax中用起来很痛苦.   ...

  3. 解决Swift中callback循环引用 - Delegated(Library)

    文章目录 前言 使用示例 一般闭包示例 Delegated 示例 源码解析 示例Demo 示例Demo地址 前言 在Swift中我们使用闭包(Callback)的时候经常要写 [weak self] ...

  4. ios开发 循环引用 检测_iOS开发——Block引起循环引用的解决方案

    [目前总结了一下,在iOS平台容易引起循环引用的几个场景:一.parent-child模式二.block(编译器会提示警告)三.NSTimer] up vote 0 down vote favorit ...

  5. Jmeter引用外部Java文件的三种方式

    首先,我们来了解一下Jmeter引用外部Java文件的应用场景:说一个最常见的场景,比如做接口测试时,登录接口密码为加密传输,加密的算法由后端开发提供,只要后端开发语言是Java,那么他提供给你的加密 ...

  6. java循环满足跳出_java跳出循环的几种方式

    java跳出循环的集中方式 目录 一.break.continue.return 二.循环标记使用 很简单的几个知识,但是久了不用就忘记了,这里记录一下,方便后面回来查看. 一.break.conti ...

  7. Nginx部署静态页面及引用图片有效访问的两种方式

    nginx安装百度一下有很多,直接正题: 静态文件目录结构 file#文件位置 /home/service/file/ css js images html fonts 配置nginx.conf核心代 ...

  8. python挖矿代码_python检测挖矿特征的几种方式

    1 #!/usr/bin/python3 2 #coding:utf-8 3 from tkinter import * 4 importpsutil,linecache,ctypes,wmi5 im ...

  9. angular7中引用ng zorro antd的三种方式

    在新版本的angular中使用新的ng zorro,按照官方文档一步一步来,没有报错,但是也没有反应. 试了一下官方的两种方式,第一种方式如果使用cnpm会报错,第二种方式会没有反应,也是因为使用了c ...

最新文章

  1. android xposed 编译,Xposed修改特征编译
  2. angular中如何定义全局变量_angularjs 设置全局变量的方法
  3. 1203正规式转换为有穷自动机
  4. CF1063F-String Journey【SAM,线段树】
  5. [css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢?
  6. 超有趣的灵魂都在看什么?
  7. paip.提升用户体验---文件查找
  8. 基于微信小程序的课堂考勤系统的设计与实现
  9. RINEX3.05格式中的主要更新
  10. Java8遍历Map、Map转List、List转Map
  11. 云上财务经营的成本管理
  12. be idle sometimes to_一生中不该错过的经典语录,深刻有道理,看了让人爱不释手!...
  13. Word文档丢失找回之没有保存Word文档就关闭了怎么解决
  14. 互联网+废品回收小程序,废品回收小程序,废品回收小程序平台,蚂蚁废收小程序
  15. KCNScrew Pack for mac(Mac序列号查询软件)
  16. 实验吧-证明自己吧(超详细)
  17. 《C语言点滴》参考文献
  18. 字节带货新大陆,抖音如何做好跨境电商这门生意?
  19. 芯片开发工具IAR Embedded Workbench for ARM 7.50.2
  20. 广州技术沙龙第 3 期报名开始!

热门文章

  1. WF4 常用类第二篇
  2. 微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现[转]
  3. SQL性能第1篇:关系优化
  4. 夸计算机老师的成语,夸赞老师的成语
  5. python图像加坐标_Python使用matplotlib模块绘制图像并设置标题与坐标轴等信息示例...
  6. java8使用stream操作集合类,如何使用bigDicemal计算工资?
  7. 坑爹的公交卡充值的流程
  8. mysql 命令 select_Mysql基础命令(二)select查询操作
  9. 客户端通过SSH private key 登录远端服务器
  10. 关于Zipkin的几个问题