fastjson 很好,但不适合我!

2023-11-08

Java指南:https://java-family.cn

FastJson 在国内的热度还是挺高的,受到了很多开发者的喜欢。不过,我自己倒没有在项目中用过。我记得刚工作那会新做的一个项目有明确规定禁止使用 FastJson。

昨天看到一篇关于 FastJson 的文章,这位朋友分享了自己在使用 FastJson 遇到的一些问题。原文地址:https://juejin.cn/post/7215886869199863869

下面是正文。

  • 记者:大爷您有什么特长呀?

  • FastJson:我很快。

  • 记者:23423 乘以 4534 等于多少?

  • FastJson:等于 2343.

  • 记者:??

  • FastJson:你就说快不快吧!

这个略显马丽苏的标题,各位看官将就着看吧。主要是怕被喷。FastJson 真的很好,我用不用我喜不喜欢的,太不重要了,我只是觉得不适合我而已。

话说以前 Gson 用得好好的,同事极力推荐我使用 FastJson,说很快云云。尽管我们的系统根本感知不出来这点速度差异。

之前也听说 FastJson 爆出来什么重大漏洞,但对我们基本没什么影响,所以这一点倒是没什么偏见。

然后在一个新项目上,脑抽抽,把 Gson 换成了 FastJson,Spring Boot 默认支持的 Jackson 换成了 FastJson。

然后就开始遇到了一些问题。先声明,这真不是尬黑,为了文章效果,故意网上扒些黑料拼凑起来,本文所提到的问题,都来源于本人最近项目的真实经历。

dateformat 优先级

本来是一个风和日丽的下午,一个非常简单的改动需求。接口返回的时间只需要年月日日期类型不需要时分秒。因为我配置全局时间格式化为yyyy-MM-dd HH:mmss,于是我愉快的在 javabean 的属性上加了个注解。

ff76f7c0fd68108de2a660424d8aad91.png

本地测试一下,没问题,提交到测试环境,搞定,完美。

然后就接到产品的疑问,改动呢?

我登上去看了一下,唉,没改到啊,日期还是带了时分秒。我大意了啊,这么小的改动,又是在测试环境,就没加验证。

6d7005249ca1670c3601327bd848bfde.jpeg

那么现在的直接问题是:FastJson 关于时间配置在局部的配置没有生效,使用的还是全局配置。

现象是,开发环境 Windows 上没有问题,测试环境 Linux 上出现了问题。两者有什么区别呢?系统问题?

既然怀疑是两个系统导致的问题,那么就在 idea 里模拟一下 linux 系统。在 VM options 添加 -Dos.name=linux

这不能完全模拟 linux 系统,只针对通过System.getproperty("os.name")来判断当前系统做某些操作的时候有用。

通过这种方式没复现,我又想到了远程调试。

一阵操作猛如虎,远程调试倒是能进断点,只是断点进不了第三方 jar 包的源码。等于白搞。

得,还是回到源码吧。拉下源码,断点,观察 JSONSerializer 类,主要是writeWithFormat方法。没有发现问题。

因为怀疑是系统导致的,在源码中搜索'linux''unix'关键字,没有发现。断点整个流程重点观察了一下这部份也没有发现问题。

突然在 JSONSerializer.dateFormatPattern上发现了这段注释。

64a86044efdaa3cf192c63cc3085cb12.png

这部份涉及到了调整 dateformat 的问题,重点在这个#1868,这通常是 github 的问题编号。

1.对于开源项目来说,解决了 BUG,通常会把问题编号放到注释里面去。前提是注释有必要。通过问题编号可以看到问题的前因后果。

2.通常来说,对于 github 开源项目都有 issue 区,拿着这个到编号直接到 issue 一搜就能搜到。

3.但也有一些项级项目,如 spark,flink 是没有 issue 区的,它们的类型问题发现描述追踪都使用 jira 平台。如:https://issues.apache.org/jira/browse/SPARK-38349

在提交 PR 的时候标题也严格按照[jira 编号][spark 子模块(如core/sql) title]的规则来。

所以拿着这个编号到issue区,不管有没有issue区,也都可以直接到pullrequest区直接搜索,就算 PR 标题里没有问题编号,PR 描述肯定也是有的,只要是有严格 PR 流程的开源项目。

所以这个问题在这里:https://github.com/alibaba/fastjson/issues/1868 。

相应的 PR 在这里:https://github.com/alibaba/fastjson/pull/2706 。

通过 ISSUES 描述的已知信息,可以看出他遇到的问题跟我是一样的,而这个问题早在 2018 年就提出了。但问题描述不太专业,没有涉及到环境以及最重要的 FastJson 的版本问题。

而通过 PR 可知,这个问题最终在 2020 才解决,期间仅在 ISSUES 区提出的相同问题就有 #1868 #1968 #2029 #24524 个。

解决问题的版本为:1.2.72.

这个信息很关键。我对照了我开发环境的版本,是高于 1.2.72 的,所以没有出现测试环境的问题。

所以,柯南告诉我们,排除了所有可能性,剩下的哪怕再可笑,也是最终问题所在。

那就是,测试环境所用的 FastJson 版本是低于 1.2.72 的。

这种可能性是存在的,因为我们用的是 maven 打代码包,依赖包单独存在。

我最终在测试环境的依赖包目录下发现了两个 Fastjson 包,果然不出所料,有一个 1.2.53 的低版本,它就是罪魁祸首。

所以,最终这个问题有相当大的程度是由于我们团队自身问题引发的。但通过解决这个问题的过程也发现了一些有意思的情况。

首先,FastJson 在某一个版本为什么会引发这个问题。它肯定是某个 PR 改出问题的,rv,testcase 覆盖没有到位。

其次,从试图解决这个问题的 3 个 PR 的时间线,分别在 2018 年,2019 年,2020 年。说明,FastJson 这个项目的 contributor 看起来有百来人,但其中过于依赖其中某 1 个或者某些主力人员。精力有限,某些优先级不那么高的 BUG 只能放任。

a74ce306de4a4449ff4747fcf3c86e5b.png

同时这个项目的荣誉感并没有那么高(或者叫并没有那么吸引高手),它并不是 Apache 顶级项目,要是其它诸如 Spark、Flink、Spring,哪怕是 Dubbo 呢,很想象这些项目会有一个并不算复杂的 BUG 悬而未决长达 3 年时间。在这些顶级开源项目,大家都是拼了老命的想找些 BUG 来提交 PR。

当然,以上只是我个人的一点猜测。

复盘,遇到 FastJson 的问题,一开始就应该奔着 github 的 issues 区,它大概率已经被前人踩坑了。

$ref 循环引用问题

fffe1fd4551866e42b0cf10a46959034.png

以上测试接口返回前端什么?

baef277e951d325d7b5cd03d3201cf67.png

我现在并不知道什么循环引用检测,这时候它是我的知识盲区。此时,我观察到的现象是,youngchildren两个 list 对象中均引用指向了王麻子这个对象。然后,在第 2 次children引用的时候它在序列化的时候直接指向了第 1 个young里相应对象引用。当然遇到这个问题的时候,我在仔细观察排除了非 fastjson 的问题以后,这次我学聪明了,我直接来到了 Github 的 issues 区,搜索$ref

2cd7d19942f15abeecbed26c7c72eb69.png

果然有很多同道中人,近 150 个问题,从时间上来看还挺新鲜。我点击了 closed,既然关闭了,那肯定解决了吧。

我点进了 closed 区第一个问题,然后作者让升级到 fastjson2。???

084055d559494b10c9fbdf20541d886c.png

如果我没有理解错,FastJson 和 FastJson2 可不是两个版本的区别,是两个项目也!据说 API 也有兼容性问题。直接这样升级过去,谈何容易!

我觉得这也是个槽点,FastJson 好像并没有一个稳定维护的版本,遇到问题总是在升级,升级的过程中也没做好质量控制,又引入了新的问题。

还是在当前项目寻求解决方法吧,哪怕升版本也好啊。终于在另一个问题下面找到了问题所在以及解决方案。

https://github.com/alibaba/fastjson/issues/3643

我现在知道这是由于循环引用检测引起的。通过设置SerializerFeature.DisableCircularReferenceDetect可以避免这个问题。

但是,我的代码其实并没有循环引用啊,只是两个子对象引用了同一个对象而已。这算什么?误伤吗?

更重要的,一些控制权应该在使用者手里?

比如,当前这个循环引用在序列化会出的问题,应该是用户手动去开启,而不是默认给用户开启。在优先级上,全局应该关闭,在有循环引用的地方,让用户选择局部开启。

现在我的前端并没有使用 FastJson,面对"$ref":"$.result.young[1]"这种文本,它能解析吗?它不能呀。

我测试了一下,好像使用 FastJson 也并不能解析回来:

2ed1800d27c6e6587960ff85f0f10b6e.jpeg

注 :经提醒,这里应使用完整报文解析,经测试,确实可以。感谢提醒!

更可怕的问题是,刚好在测试环节有两个子对象引用了同一个对象,被我提前发现了。如果测试环境没有这样的情况,在生产环境刚好遇到了呢?那就是生产事故了呀。

本来是一个挺好的设计点,能起到锦上添花的作用,但它却可能暴雷,这是好心办坏事。

同样的,还有SerializerFeature.WriteMapNullValue。如果一个字段值为null,fastjson 默认就不返回该字段了。本来前后端约定好,如果为null就怎样处理的逻辑,可能在生产环境中突然暴雷啊。

就像WriteNullListAsEmpty就很好,不错的设计点,如果返回的 list 为null的时候,用户可以选择让它序列化为[],但它也不是默认开启的呀,给了用户额外的选择权,对吧。

总结

写到这里的时候,我是真心觉得 FastJson 有比竞品有些特色的地方。这真不是为了所谓的客观公正,非要负面写多点,再搞点正面的。

为了写文章,那肯定要去试验,得把竞品也拿出来测试一下,一测试发现并不是 FastJson 独有的,尴尬!

但我还是那句话,不管你信不信,对于开源项目,特别是这样一个广泛使用的开源项目,肯定有非常值得学习的地方。一个开源项目,如果整天拿着显微镜去观察,那肯定能找出不少毛病。

这里稍微总结一下本文的信息点。并不一定是某个具体 BUG,而是通过这个 BUG,解决这个 BUG 背后所展现出来的 FastJson 的信息或趋势。

  1. review,testcase 覆盖不是很到位

  2. contributor 看起来很多,但严重依赖主力人员。而主力精力有限,某些优先级不那么高的 BUG 只能放任。

  3. 这个项目的荣誉感并没有那么高,或者叫并没有那么吸引高手)。

  4. 有些功能点应该把控制主动权交给用户,如 DisableCircularReferenceDetect,WriteMapNullValue 等。默认开启非常容易导致线上暴雷。

  5. 作者已经全面转向 fastjosn2,而且哪怕在这之前,对于 fastjson 没有一个稳定维护的版本,不断升级,不断引入新问题。

祝愿 fastjson2 越来越好,不要步 struts2 的后尘。

10625402cae20676e37bb151e3a529f9.jpeg 来源:网络

ce225876813d92b901e54df80f05a3a9.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

fastjson 很好,但不适合我! 的相关文章

  • MinGW、GCC、qMake等编译工具的区别

    MSVC在Windows下编译C和C gcc g 分别是GNU的C 和 C 编译器 在Linux 下面用 cmake qmake分别用来编译C和QT工程 输入是makefile 输出结果是可执行文件 编译的过程会调用编译器和连接器来完成整个
  • 百万并发服务器设计

    文章目录 前言 1 改造ntyreactor 2 如何管理eventblock 创建一个eventblock 查找对应fd在那个eventblock上 具体使用 3 总结 前言 本文的基础以及使用的代码模型都继承自上一篇文章 所以请先详细阅
  • 大模型时代下做科研的四个思路

    背景 在模型越来越大的时代背景下 如何利用有限的资源做出一些科研工作 四个方向 1 Efficient PEFT 提升训练效率 这里以PEFT parameter efficient fine tuning 为例 2 Existing st
  • linux查看磁盘IO,网络IO 总结

    一 linux查看磁盘IO 网络 IO可用的命令 1 top 监控整体服务器 cpu 内存 磁盘 网络等 2 dstat d 查看当前磁盘每秒的读取 写入量 单位K 3 dstat r 查看当前磁盘随机的读IOPS 写IOPS 4 dsta
  • 一款简单的角度计算Python包:PyAngle

    一款简单的角度计算Python包 PyAngle GitHub仓库 gzn00417 PyAngle PyPI项目 PyAngle A simple package for angle calculation Use pip install
  • ubuntu下载的国内镜像

    阿里云镜像
  • 惊爆GPT OpenAPI的调用以及API内的参数详解

    开篇 随着人工智能技术的飞速发展 自然语言处理技术 NLP 在过去几年也取得了突飞猛进的突破 在这个过程中 一个重要且可称为颠覆者的模型 GPT 3 第三代生成式预训练 Transformer 模型 的诞生 无疑大大加速了 NLP 领域的前
  • 以太坊智能合约安全编程最佳实践smart-contract-best-practices

    https github com ConsenSys smart contract best practices Ethereum Contract Security Techniques and Tips The recent attac
  • Web UI自动化测试之Selenium工具篇

    本文大纲截图 一 自动化测试介绍 1 基本介绍 1 1 自动化 概念 由机器设备代替人工自动完成指定目标的过程 优点 1 减少人工劳动力 2 提高工作效率 3 产品规格统一标准 4 规模化 批量生产 1 2 自动化测试 软件测试 校验系统是
  • 今天我抓了个 HTTPS 的包

    之前写过一篇讲 HTTPS 的思想的文章 破玩意 用 HTTPS 传纸条 后来又写了篇用更凝练的语言总体描述了 HTTPS 的主干 叮咚 HTTPS 的分支和主干 想必通过这两篇文章 HTTPS 为什么要这么设计 以及它是用来解决什么问题的
  • Android 使用retrofit解析接口返回的xml格式数据

    直接入正题 需要解析的数据格式为 从数据格式上看 上面都是单个字段的解析 下面则是一个数组 解析过程 1 添加retrofit预返回数据处理类型 2 添加返回数据处理类 也就是后面会用的 在上图中可以看到将xml的数据结构在XmlLogin
  • Matlab实现神经网络(附上100个完整仿真源码+说明文档+数据)

    神经网络是一种模仿人类神经系统 以处理信息为目的的计算模型 它由大量节点 或称神经元 和连接它们的边组成 每个节点代表一个变量 边表示变量之间的关系 在神经网络中 信息通过节点之间的连接传递 并在各个节点之间进行处理和转换 Matlab是一
  • 算法:求最长回文数

    题目 给定一个字符串 s 找到 s 中最长的回文子串 你可以假设 s 的最大长度为 1000 eg 输入 babad 输出 bab 注意 aba 也是一个有效答案 eg 输入 cbbd 输出 bb C 采用动态规划 是学习别人的 但在lee
  • 视频清晰度、色偏以及亮度异常检测

    转自 http blog csdn net kklots article details 12720359 昨天老板临时交代一个活 要求通过算法检测监控设备是否存在失焦 偏色 亮度异常等问题 问题本身不难 在网上查看了一些资料 自己也做了一
  • 谈谈深度学习中的模型集成

    前文已经给出了三种可提升模型性能的方法论 残差连接 正则化和深度可分离卷积 本文提出另一种强大的技术是模型集成 model ensembling 集成是指将一些列不同模型的预测结果汇集到一起 从而得到更好的预测结果 集成依赖于这样的假设 即
  • adb push安装系统应用(并自启)

    1 有root权限 adb push 安装应用 system app或者system priv app 法一 对于多设备连接时用 s devicename选择设备 当adb启动失败时 用adb kill server 和adb start
  • 如何在一台电脑安装多个版本的JDK

    如何在一台电脑安装多个版本的JDK 一 打开JDK下载官网网址 下载链接 在里面选择你想要的版本进行下载 下载方式参考我的上一篇笔记 二 JDK安装路径 我这里装了1 8和17两个版本 可以把这两个不同版本放在一个大的文件夹里 方便操作 也
  • JMETER接口测试_用户登录(MD5加密)

    JMETER接口测试 用户登录 密码MD5加密 1 给整个线程组 添加全局变量 TestPlan gt 线程组 gt 右键 gt ADD Config Element gt User Defined Variables 全局变量的意思 整个
  • Hbuildx创建vue3项目

    静态网站 H5 跳小程序 微信开放文档 一 vue3的试水学习 vue3的项目 可以先尝试普通项目的vue3应用 根据示例来看 是vue3的语法没错了 可以先在这儿试一下基础的的vue3语法 vue的setup 单文件组件 这是vue3的s
  • 英特服务器的spec整数性能,单线程整数运算性能:SPEC CPU2006_商用-中关村在线

    即使在服务器市场也是高核心数的CPU称雄 单线程高性能表现依然值得拥有 它确保在任何情况下都能保证一定的性能发挥 而不是仅仅为了 embarrassingly parallel 易并行计算 软件的 throughput situations

随机推荐

  • Unity遮罩实现汽车后视镜(附效果图)

    话不多说 先上效果图 最近项目有用到Unity实现汽车后视镜功能 网上找了很多例子 比如这篇文章 原理确实如此 但只是在平面上实现 我想改变平面改成汽车后视镜形状 这就出现了问题 镜子效果变扭曲 我想是因为相机投射是矩形 如果你改变平面形状
  • 机器学习之梯度下降(BGD,SGD, MBGD)

    梯度下降 批量 梯度下降法 BGD 随机梯度下降 SGD 小批量梯度下降法 MBGD 梯度下降 批量 梯度下降法 BGD 1 递推公式推导过程 通过多项式对函数进行逼近的方法得到 f x f
  • 阿里CDN技术

    构建高效 安全的CDN 阿里CDN核心技术揭秘 阿里云 核心系统部 朱照远 叔度 大纲 总览 性能优化 安全防御 展望 阿里自身面对的技术挑战 2012年淘宝 天猫的交易额为11600亿元人民币 超过Amazon与eBay之和 三个网站流量
  • SPI接口详细介绍

    1 概述 SPI Serial Peripheral Interface 是串行外围设备接口 是一种高速 全双工 同步的通信总线 常规只占用四根线 节约了芯片管脚 PCB的布局省空间 现在越来越多的芯片集成了这种通信协议 常见的有EEPRO
  • MySQL基础篇-第16章_变量、流程控制与游标

    第16章 变量 流程控制与游标 讲师 尚硅谷 宋红康 江湖人称 康师傅 官网 http www atguigu com 1 变量 在MySQL数据库的存储过程和函数中 可以使用变量来存储查询或计算的中间结果数据 或者输出最终的结果数据 在
  • python3 flask接收数据处理

    from flask import Flask import time app Flask name app route def index return Hello pyhon app route time def t now time
  • WeBASE-Front中间件搭建

    WeBASE Front中间件搭建 简介 WeBASE WeBank Blockchain Application Software Extension 是在区块链应用和FISCO BCOS节点之间搭建的一套通用组件 围绕交易 合约 密钥管
  • vector和list有什么区别?分别在什么场景下应用?

    Vector 顺序表 优点 和数组类似开辟一段连续的空间 并且支持随机访问 所以它的查找效率高其时间复杂度O 1 缺点 由于开辟一段连续的空间 所以插入删除会需要对数据进行移动比较麻烦 时间复杂度O n 另外当空间不足时还需要进行扩容 Li
  • 基础路由概念及配置

    前言 一 路由的概念 1 路由的分类 2 路由表的作用 二 中小型企业路由规划 1 静态路由规划介绍 2 静态路由规划 3 默认路由规划 4 浮动路由规划 总结 前言 路由就是源主机到目标主机的转发过程 一 路由的概念 1 路由的分类 1
  • 误删除oracle datafile,无法打开数据库

    1 在oracle open方式下 直接从OS上删除了datafile文件 rm u02 rmants dbf 2 数据库关闭后 无法打开数据库 只能到mount状态 SQL gt alter database open alter dat
  • 批量操作关联事务没有滚机制怎么办?交给递归就好了!

    最近遇到一个问题 需要批量修改Nginx配置文件 并分别执行Reload操作 文件更新和reload是lua脚本完成的功能 java后台可以直接调动接口 但问题是需要批量update并分别reload 而且没有事务控制 也就是说在更新第十条
  • jmeter-常用的几种参数化

    jmeter常见的几种参数化方式 jmeter 的csv 数据文件设置 线程组 gt 配置元件 gt Csv数据文件配置 Filename 文件名 File encoding 编码格式 variable Names 参数名称 后面可以使用v
  • C++.将十个整数从小到大顺序排序(冒泡排序法+反向冒泡排序)

    先说一下冒泡排序法的思路 若n个整数则需要进行n 1轮 每轮 将两个相邻元素进行对比 若左大于右则交换 第一轮需要比较n 1次 第二轮n 2次 每轮结束后 最大的元素就会去到最右边 第二轮倒数第二大就会去到最右边 所以 见代码 int ma
  • RIP笔记

    目录 RIP路由信息协议 UDP520端口 RIPNG521端口 RIP使用的算法 贝尔曼 福特算法 RIP的版本 RIP的数据包 RIP的工作过程 RIP的计时器 周期更新计时器 默认30s 失效计时器 默认180s 垃圾回收计时器 默认
  • 【深度学习与计算机视觉】4、反向传播及其直观理解

    四 反向传播及其直观理解 4 1 引言 问题描述和动机 大家都知道 其实我们就是在给定的图像像素向量x和对应的函数 f x f x f x 然后我们希望能够计算
  • 使用决策树对数据进行分类——识别橘子苹果

    代码如下 encoding utf 8 from sklearn import tree 1表示光滑 0表示粗糙 features 140 1 130 1 150 0 170 0 0表示苹果 1表示橘子 labels 0 0 1 1 创建一
  • 手把手教你在win10搭建linux虚拟机

    由于企业几乎都用linux作为生产环境 linux逐渐成为了工程师的必学知识 本文将带你如何在安装 虚拟机 在虚拟机中安装centOS linux的一个发行版 以及如何在 linux安装docker 并使用docker安装mysql red
  • Playing with ptrace, Part II

    Playing with ptrace Part II From Issue 104 December 2002 Dec 01 2002 By Pradeep Padala in SysAdmin In Part II of his ser
  • Hyperledger Fabric官方文档——Introduction

    研究生一直在折腾区块链这方面的东西 翻来覆去感觉Hyperledger Fabric是个挺有前景的 怎么说呢 方向吧 自己脑子里想的东西全让它实现了 又觉得难过又觉得开心 超级账本值得学习的地方有很多 又打算把官方文档翻出来读一遍 因为英语
  • fastjson 很好,但不适合我!

    Java指南 https java family cn FastJson 在国内的热度还是挺高的 受到了很多开发者的喜欢 不过 我自己倒没有在项目中用过 我记得刚工作那会新做的一个项目有明确规定禁止使用 FastJson 昨天看到一篇关于