fastjson 返回 $ref 数据
文章目录
- 问题描述:
- 1、重复引用:
- 2、循环引用:
- 原因分析:
- 1、重复引用:
- 2、循环引用:
- 反序列化:
- 1、开启引用检测:
- 2、关闭引用检测:
- 小结:
问题描述:
问题现象:
通过 fastjson 序列化的结果是这样的:
[{"name":"张三"},{"$ref":"$[0]"}]
即 序列化结果中,出现了 $ref 这类引用信息,首先猜测是由于某些规则的限制导致。
我们来演示下问题是如何出现的,先定义实体类:
data class Person(var name: String,var rel: Person? = null
)
1、重复引用:
@Testfun test() {val parseObject = JSONObject.parseObject("{\"name\":\"张三\"}")val list: ArrayList<JSONObject> = Lists.newArrayList()list.add(parseObject)list.add(parseObject)println(JSONArray.toJSONString(list))}
输出:[{"name":"张三"},{"$ref":"$[0]"}]
2、循环引用:
简单来说就是 A 引用了 B,B 又引用了 A,造成了环形依赖,fastjson 默认会处理成 引用的形式,总之,不会抛错:
@Testfun test() {val a = Person(name = "zs")val b = Person(name = "lisi")a.rel = bb.rel = aprintln(JSONArray.toJSONString(Lists.newArrayList(a, b)))}
输出:[{"name":"zs","rel":{"name":"lisi","rel":{"$ref":".."}}},{"$ref":"$[0].rel"}]
原因分析:
先说结论:序列化结果中出现 $ref 这类关键字,是由 fastjson 特定的规则决定的。为什么要这样设计?
主要原因是循环引用本身就是错误的写法,你引用我、我引用你,什么时候到头?
所以,fastjson 就会直接往外抛 StackOverFlow 异常。虽然没得问题,但还是不算友好,为此,要想一种方法解决循环依赖的问题,这个部分在 fastjson 中就设计了 引用检测机制,并默认开启。
我们来看看有哪些解决方法:
1、重复引用:
这个能解决:
- 如果你代码写错了,本身不应该出现重复引用的情况,请直接改代码!
- 如果你确实有重复引用这个需求,使用 SerializerFeature.DisableCircularReferenceDetect 特性关闭引用检测
改正后:
@Testfun test() {val parseObject = JSONObject.parseObject("{\"name\":\"张三\"}")val list: ArrayList<JSONObject> = Lists.newArrayList()list.add(parseObject)list.add(parseObject)println(JSONArray.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect))}
输出:[{"name":"张三"},{"name":"张三"}]
2、循环引用:
这个没法解决。循环引用本身就不该出现,这个时候你只能改正你的代码。
这里,我们把 SerializerFeature.DisableCircularReferenceDetect 特性关掉,然后看看效果:
@Testfun test() {val a = Person(name = "zs")val b = Person(name = "lisi")a.rel = bb.rel = aprintln(JSONArray.toJSONString(Lists.newArrayList(a, b), SerializerFeature.DisableCircularReferenceDetect))}
直接抛出了异常:
java.lang.StackOverflowErrorat java.base/java.lang.String.getChars(String.java:863)at com.alibaba.fastjson.serializer.SerializeWriter.writeFieldValueStringWithDoubleQuoteCheck(SerializeWriter.java:1884)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)at com.alibaba.fastjson.serializer.ASMSerializer_1_Person.writeDirectNonContext(Unknown Source)...
反序列化:
fastjson 提供了这套引用机制,对相同的引用使用了 $ref 来代替,如果用这样的序列化结果,再反序列化,会得到什么样的效果?
1、开启引用检测:
即,我们直接使用 [{"name":"张三"},{"$ref":"$[0]"}] 字符串反序列化:

可以直观的看到,得到的是同一个引用对象。
2、关闭引用检测:
即,直接使用 [{"name":"张三"},{"name":"张三"}] 进行序列化:

可以看到,得到的就是不同的对象了。
小结:
对于重复引用,加上SerializerFeature.DisableCircularReferenceDetect 可以解决 $.ref 显示问题。
对于循环引用,加上SerializerFeature.DisableCircularReferenceDetect 会抛 SOF 异常,没法解决,只能修改代码
相关文章:
fastjson 返回 $ref 数据
文章目录问题描述:1、重复引用:2、循环引用:原因分析:1、重复引用:2、循环引用:反序列化:1、开启引用检测:2、关闭引用检测:小结:问题描述: 问题…...
Zookeeper特性和节点数据类型详解
什么是ZK? zk,分布式应用协调框架,Apache Hadoop的一个子项目,解决分布式应用中遇到的数据管理问题。 可以理解为存储少量数据基于内存的数据库。两大核心:文件系统存储结构 和 监听通知机制。 文件系统存储结构 文件目录以 / …...
Java代码是如何被CPU狂飙起来的?
无论是刚刚入门Java的新手还是已经工作了的老司机,恐怕都不容易把Java代码如何一步步被CPU执行起来这个问题完全讲清楚。但是对于一个Java程序员来说写了那么久的代码,我们总要搞清楚自己写的Java代码到底是怎么运行起来的。另外在求职面试的时候这个问题…...
Dynamics365安装失败解决及注册编写
一、修改错误昨天登录报错今天开始返回我之前设置的断点开始重新配置,Reporing Services配置完成后发现dynamics365还是下载失败之后下载了一上午dynamics365就一直卡在最后的界面进度条不动索性我直接把所有环境都卸载了 连同虚拟机卸载重装终于在下午的时候dynami…...
Kafka 集群参数
Kafka 集群参数Broker 端参数存储配置ZooKeeper 配置Broker 连接配置Topic 管理配置数据留存配置Topic 级别参数JVM 参数操作系统参数重要的配置 : Broker 端参数,主题级别的参数、JVM 端参数、操作系统级别的参数 Broker 端参数 存储配置 log.dirs:指…...
等保2.0与1.0 测评要求的变化
No.1标准内容增加了 标准内容上最大的变化就是将安全要求分为了安全通用要求和扩展要求。首先,安全通用要求部分已对1.0标准的内容进行了优化,删除或修订了过时的要求项,新增了对新型网络攻击行为防护和个人信息保护等方面的新要求。其次&am…...
nodejs学习巩固笔记-nodejs基础,Node.js 高级编程(核心模块、模块加载机制)
目录Nodejs 基础大前端开发过程中的必备技能nodejs 的架构为什么是 NodejsNodejs 异步 IONodejs 事件驱动架构全局对象全局变量之 process核心模块核心模块 - path全局变量之 Buffer创建 bufferBuffer 实例方法Buffer 静态方法Buffer-split 实现核心模块之FS模块文件操作 APImd…...
2023年春【移动计算技术】文献精读(二)-3 || 附:创新点、创新思想和技术路线总结
榜样的力量是无穷的! 🎯作者主页:追光者♂ 🌸个人简介:2022年CSDN博客之星人工智能领域TOP4🌟、阿里云社区专家博主🏅 CSDN-人工智能领域新星创作者🏆 【无限进步,一起追光!】 🍎欢迎点赞👍 收藏⭐ 留言📝 🌿本篇,仅接着上两篇,为【移动计算技术】…...
企业新闻稿的格式和要求是什么?如何写好新闻稿?
新闻稿是企业自己撰写给媒体的新闻素材,媒体采纳你的稿件后就可以传播到更多的大众面前。 所以企业新闻稿的撰写一方面要让媒体认可,另外一方面是让用户认可你的品牌或是产品。 企业新闻稿的格式和要求是什么?如何写好新闻稿?今…...
String类的底层原理和版本演变
1 String类的底层演变(1) JDK8以及之前版本 (2)JDK9以及之后版本 javaJDK8的字符串存储在char类型的数组里面,在java中,一个char类型占两个字节。但是很多时候,一个字符只需要一个字节就可存储&…...
软考高级信息系统项目管理师系列之二十三:项目采购管理
软考高级信息系统项目管理师系列之二十三:项目采购管理 一、项目采购管理内容整理二、项目采购管理1.采购的定义2.项目采购管理3.战略合作管理三、规划采购1.供应商管理2.采购需求与计划3.规划采购的输入、输出、工具和技术四、实施采购1.采购合同知识2.实施采购的输入、输出、…...
SpringMVC-0308
五、域对象共享数据0、三个域对象范围request:一次请求 第1~6都是向request共享session:一次会话(浏览器开启到浏览器关闭,与服务器关闭无关,session有钝化和活化操作,可以持久化数据࿰…...
[数据结构]:14-选择排序(顺序表指针实现形式)(C语言实现)
目录 前言 已完成内容 选择排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortCommon.cpp 05-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代…...
基于C/C++综合训练 ----- 贪吃蛇
文章目录一、定义结构体对象二、游戏初始化1. 蛇初始化2. 食物初始化3. 围墙初始化4. 界面初始化三、逻辑编程1. 启动游戏2. 打印成绩3. main函数四、细节处理五、程序源码该篇环境为Visual Studio2022 游戏简述 :在控制终端绘画出一个矩阵表示游戏界面(围墙)&…...
Unity 混合操作(Blending)
渲染图形时,在执行所有着色器并应用所有纹理后,像素将写入到屏幕。这些像素与已有像素的组合方式由 Blend 命令控制。用于生成透明对象。《Unity Shader入门精要》大致解释:片元通过了模板测试和深度测试之后,会进行混合步骤。如果…...
Hive建表高阶语句
CTAS -as select方式建表CREATE TABLE ctas_employee as SELECT * FROM employee;CTE (CTAS with Common Table Expression)CREATE TABLE cte_employee AS WITH r1 AS (SELECT name FROM r2 WHERE name Michael), r2 AS (SELECT name FROM employee WHERE gender Male), r3 …...
面向新时代,海泰方圆战略升级!“1465”隆重发布!
过去四年,海泰方圆“1344”战略一直在引领公司前行,搭建了非常坚实的战略框架基座,并推动全员在实践和行动中达成深度共识。 “1344”战略 1个定位,代表着当前机构用户的一组共性需求,密码安全数据治理信创工程。 3…...
带你感受一次JVM调优实战
本文分成两部分,先了解理论,然后再进行实战。 理论篇 1.1 调优目标 JVM调优的两大目标是: 提高应用程序的性能和吞吐量: 通过优化JVM的垃圾回收机制、调整线程池大小和优化代码,可以提高应用程序的性能和吞吐量。…...
ALG和STUN
目录 ALG 应用层网关讲解 Client1使用FTP主动模式建立FTP Client1使用FTP被动模式建立FTP STUN讲解 ALG 应用层网关讲解 用来替换应用层信息 Client1使用FTP主动模式建立FTP 主动模式:服务器收到客户端发来的请求FTP的地址和端口 服务器使用20端口直接向客户端建…...
原生HTML放大镜
该放大区域用背景图片放大 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compat…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
