Fastjson出现$ref问题

2023-11-09

解决FastJson中“$ref 循环引用检测”的问题的几种方式
一、现象:

项目中用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配置增加以下项:

 static {
        // 全局配置关闭Fastjson循环引用,避免出现$ref
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }
/**
 * FastJson配置类
 *
 * @author wyb
 * @date 2023/01/01 00:00 周六
 **/
@AutoConfiguration
public class FastJsonConfig {

    static {
        // 全局配置关闭Fastjson重复引用,避免出现$ref
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }

    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {

        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.APPLICATION_JSON);

        /****************************FastJsonConfig Start*****************************/

        com.alibaba.fastjson.support.config.FastJsonConfig fastJsonConfig = new com.alibaba.fastjson.support.config.FastJsonConfig();
        // 序列化配置
        SerializeConfig serializeConfig = new SerializeConfig();
        // BigInteger、Long转JSON精度丢失配置
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);

        // 序列化值为null的字段
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.PrettyFormat
                , SerializerFeature.WriteNullListAsEmpty
                , SerializerFeature.WriteMapNullValue
                //, SerializerFeature.WriteNullStringAsEmpty
                //, SerializerFeature.WriteNullNumberAsZero
                //, SerializerFeature.WriteNullBooleanAsFalse
        );

        fastJsonConfig.setSerializeConfig(serializeConfig);
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);

        /****************************FastJsonConfig End*****************************/

        converter.setSupportedMediaTypes(mediaTypes);
        converter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(converter);
    }
}

但是因为全局配置是在我们项目的基础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;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Fastjson出现$ref问题 的相关文章

  • PostgreSQL:比较 json [重复]

    这个问题在这里已经有答案了 众所周知 目前 PostgreSQL 还没有方法来比较两个 json 值 比较就像json json不起作用 但是选角呢json to text before Then select x a y b json t
  • 与 Eclipse 中的 Java Content Assist 交互

    作为我的插件项目的一部分 我正在考虑与 Eclipse 在 Java 文件上显示的内容辅助列表进行交互 我正在尝试根据一些外部数据对列表进行重新排序 我看过一些有关创建新内容辅助的教程 但没有看到有关更改现有内容辅助的教程 这可能吗 如果是
  • 为什么即使我的哈希码值相同,“==”也会返回 false

    我写了一个像这样的课程 public class HashCodeImpl public int hashCode return 1 public static void main String args TODO Auto generat
  • 从 MATLAB 调用 Java?

    我想要Matlab程序调用java文件 最好有一个例子 需要考虑三种情况 Java 内置库 也就是说 任何描述的here http docs oracle com javase 6 docs api 这些项目可以直接调用 例如 map ja
  • 将巨大的模式编译成Java

    有两个主要工具提供了将 XSD 模式编译为 Java 的方法 xmlbeans 和 JAXB 问题是 XSD 模式确实很大 30MB 的 XML 文件 大部分模式在我的项目中没有使用 所以我可以注释掉大部分代码 但这不是一个好的解决方案 目
  • 优化数据可视化 Web 应用程序的性能

    我正在重写 3 年前编写的数据可视化网络工具 从那时起 浏览器的 JavaScript 引擎变得更快 所以我正在考虑将部分工作从服务器转移到客户端 在页面上 数据在表格和地图 或图表 中可视化 它使用相同的数据 但以不同的方式 因此准备显示
  • Runtime.exec 处理包含多个空格的参数

    我怎样才能进行以下运行 public class ExecTest public static void main String args try Notice the multiple spaces in the argument Str
  • 断言 Kafka 发送有效

    我正在使用 Spring Boot 编写一个应用程序 因此要写信给 Kafka 我这样做 Autowired private KafkaTemplate
  • Java 中如何将 char 转换为 int? [复制]

    这个问题在这里已经有答案了 我是Java编程新手 我有例如 char x 9 我需要得到撇号中的数字 即数字 9 本身 我尝试执行以下操作 char x 9 int y int x 但没有成功 那么我应该怎么做才能得到撇号中的数字呢 ASC
  • 如何在 Spring 中使 @PropertyResource 优先于任何其他 application.properties ?

    我正在尝试在类路径之外添加外部配置属性资源 它应该覆盖任何现有的属性 但以下方法不起作用 SpringBootApplication PropertySource d app properties public class MyClass
  • 如何仅从 Firestore 获取最新更新的数据?

    在 Firestore 上发现任何更改时始终获取整个文档 如何只获取最近更新的数据 这是我的数据 我需要在第一次加载时在聊天中按对象顺序 例如 2018 09 17 30 40 msg和sendby 并且如果数据更新则仅获取新的msg和se
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • 蓝牙发送和接收文本数据

    我是 Android 开发新手 我想制作一个使用蓝牙发送和接收文本的应用程序 我得到了有关发送文本的所有内容逻辑工作 但是当我尝试在手机中测试它时 我看不到界面 这是Main Activity Code import android sup
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • 为什么\0在java中不同系统中打印不同的输出

    下面的代码在不同的系统中打印不同的输出 String s hello vsrd replace 0 System out println s 当我在我的系统中尝试时 Linux Ubuntu Netbeans 7 1 它打印 When I
  • 如何通过 JsonConvert.DeserializeObject 在动态 JSON 中使用 null 条件运算符

    我正在使用 Newtonsoft 反序列化已知的 JSON 对象并从中检索一些值 如果存在 关键在于对象结构可能会不断变化 因此我使用动态来遍历结构并检索值 由于对象结构不断变化 我使用 null 条件运算符来遍历 JSON 代码看起来像这
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • java XMLSerializer 避免复杂的空元素

    我有这个代码 DocumentBuilderFactory factory DocumentBuilderFactory newInstance DocumentBuilder builder factory newDocumentBuil
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro

随机推荐

  • 区块链学习笔记13——ETH以太坊概述

    区块链学习笔记13 ETH以太坊概述 学习视频 北京大学肖臻老师 区块链技术与应用 笔记参考 北京大学肖臻老师 区块链技术与应用 公开课系列笔记 目录导航页 比特币和以太坊是两种最主要的加密货币 比特币被称为区块链1 0 以太坊被称为区块链
  • 自动驾驶开发入门(三)---浅谈Apollo Cyber RT中的Transport

    Cyber的Transport为上层封装了底层数据传输的细节 上层主要使用Transport Transmitter Receiver三个类 其中Transport是工厂类 负责创建Transmitter Receiver以及Dispatc
  • pyspark作为生产者发送消息(推送数据)到kafka

    pyspark作为生产者发送消息到kafka 网上大部分的案例都是pyspark作为消费者消费kafka的消息 但是作为生产者生产消息发送给kafka的很少 下面把pyspark如何创建数据 或读取数据 作为生产者发送消息给kafka作为案
  • C++字节对齐

    系统让程序中的变量按字节对齐的目的 访问高效 字节是内存空间分配的最小单位 在程序中 我们定义的变量可以放在任何位置 但实际情况是访问特定类型变量的时候在特定的内存地址访问 这就需要各种类型数据按照一定的规则在空间排列 而不是顺序的一个接着
  • 两台文件服务器,负载均衡,用两台云服务器搭建一个负载均衡

    用两台云服务器搭建一个负载均衡 内容精选 换一换 弹性负载均衡 Elastic Load Balance 以下简称ELB 通过将访问流量自动分发到多台弹性云服务器 扩展应用系统对外的服务能力 实现更高水平的应用程序容错性能 用户通过基于浏览
  • 顺序表的C语言实现(静态/动态)

    目录 1 顺序表的定义 2 顺序表的实现 静态分配 3 顺序表的实现 动态分配 1 顺序表的定义 线性表的顺序存储又称顺序表 它是用一组地址连续的存储单元依次存储线性表中的数据元素 使得逻辑上相邻的两个元素在物理位置上也相邻 因此 顺序表的
  • C++基础知识 - 浮点类型

    需要精确计算的数学 工程应用 用整数类型不合适 float类型 单精度浮点类型 用来存储带小数部分的数据 在内存中占用4个字节 表示范围 3 4 1038 3 4 1038 不需记忆 精度 最长7位有效数字 是指7位10进制位 精度只能取值
  • 【Android】常用对话框大全(二)Material Dialog

    前言 上一篇文章中 谈到本系列的文章将讲解Android dialog Material dialog 为何要谈论Material呢 开发过Flutter的开发者也许就会明白 Material Design框架Flutter也在用 而在其官
  • MATLAB---获取图像中的指定像素点的值(RGB图像)

    输入 clear all RGB imread 图片名 格式 r x1 y1 z1 指定像素点的横坐标 c x2 y2 z2 指定像素点的纵坐标 p impixel RGB r c 用impixel 函数来返回RGB图像的横纵坐标对应的像素
  • Java 使用枚举消除if else

    1 功能需求 if else判断时写代码过程中非常常见的 但是有些相对比较固定格式的if else判断却是我们可以尽可能避免的 其中 枚举的作用在我们消除if else代码快的作用非常大 那么 我们该如何实现呢 2 代码实现 定义枚举变量
  • 【54-Sentinel熔断、降级、限流的基本概念-Sentinel实战上手应用-actuator实时监控-Docker安装部署Sentinel教程-熔断降级实战练习-Sentinel自定义资源】

    一 知识回顾 0 三高商城系统的专题专栏都帮你整理好了 请点击这里 1 系统架构演进过程 2 微服务系统架构需求 3 高性能 高并发 高可用的三高商城系统项目介绍 4 Linux云服务器上安装Docker 5 Docker安装部署MySQL
  • Redis复习笔记

    Redis 是一个高性能的key value数据库 支持多种数据类型 String 可以是字符串 整数 浮点数 List 列表 一个链表 链表上的每个节点都包含一个字符串 Set 集合 包含字符串的无序收集器 并且被包含的每个字符串都是独一
  • Sharding-jdbc

    一 概念理解 垂直切分 包含垂直分库和垂直分表 1 1 垂直分库 专库专用 按照业务类型对表分类 1 2 垂直分表 基于数据表的列 字段 为依据切分的 是一种大表拆小表的模式 1 3 垂直切分优点 不同业务的数据进行独立维护 监控 扩展 在
  • 右键里没有新建txt文件选项 win7

    试试这个方法吧 win7的试过 成功 找个文本文档 复制一个 把里面的内容清空 改后缀为reg 点右键 编辑 把下面的内容复制进去 保存 然后双击导入注册表 Windows Registry Editor Version 5 00 HKEY
  • 建设一站式DevOps平台,腾讯云研发效能提升实践

    导语 近年来 研发效能提升越来越受到业界重视 许多厂商都在不断探索研发效能提升之路 从而实现研发效率和质量的持续优化 以应对日趋复杂的产品开发 那么腾讯云的研发效能相关工作是如何开展和落地的呢 今天我们特邀了腾讯云研发效能工作组负责人 腾讯
  • VirtualBox7.0

    文章目录 安装环境 记录目的 VirtualBox7 0安装及配置 VBox增强功能安装及共享文件夹配置 VBox增强功能安装 安装方法 共享文件夹建立 补充资料 更换系统源 anaconda安装 将bin路径加入系统path变量 增加源
  • FinClip 小程序原生页面要获取权限时该使用哪些接口?比uniapp更方便吗?

    概念 在小程序里面有一些权限需要小程序 微信 给予 比如用户手机号 运动步数 摄像头 通讯地址 iOS端 相机权限 二维码扫描接口 scanCode 选择图片接口 chooseImage 拍照 选择视频接口 chooseVideo 录像 C
  • xss绕过方法

    xss绕过方法 1 改变大小写 将大小写穿插编写 可以转换为 2 关闭标签 利用大于号 gt 关闭标签使得xss生效 gt 3 利用html标签触发事件 很多标签都可以对过滤进行绕过 格式 lt 标签 事件 执行语句 例如 p style
  • 汽车结构之仪表

    为了使驾驶员能够掌握汽车及各系统的工作情况 在汽车驾驶室内的仪表板上装有各种指示仪表 指示灯及各种报警信号装置 汽车上常用的仪表有车速里程表 发动机转速表 机油压力表 燃油表 冷却液温度 水温 表等 它们通常与各种信号灯一起安装在仪表板上
  • Fastjson出现$ref问题

    解决FastJson中 ref 循环引用检测 的问题的几种方式 一 现象 项目中用json形式来存储一个集合对象 用fastjson发现多了一些东西 ref 了解之后才发现是重复引用的问题 id 1 orderList id 2 date