API 传输数据 小心 fastjson 循环引用检测($ref)会作怪
API 传输数据时 fastjson 循环引用检测$ref会作怪一、背景在HistoryPriceHandler中需要根据一批crmId构造出多个HistoryPriceQuery再调用wso2Utils.getHistoryPrice(...)发送给 WSO2 历史价格接口。构造逻辑大致是ListHistoryPriceQuerypriceQueryHistoryPriceQuery.build(crmIdList,query);ListApimHistoryPriceResponsepriceListwso2Utils.getHistoryPrice(priceQuery);每个HistoryPriceQuery内部都持有一份mtmListCpmMtm。二、优化引发的问题出于「节约内存」的想法我把build改成了共享同一份 mtm 列表所有HistoryPriceQuery的mtm字段都指向同一个 List 对象因为每个 query 的 mtm 内容本来就完全一样。// 共享版mtm 只克隆一次所有 query 共用同一个引用ListCpmMtmsharedMtmListbuildMtmList(query.getMtm());for(...){metaQuery.setMtm(sharedMtmList);// 同一个对象}结果出现了诡异现象原来的独立克隆版本getHistoryPrice调用成功。共享 mtm 的新版本getHistoryPrice调用失败。而更迷惑的是——两个版本用System.out.println(JSON.toJSON(...))打印出来的 JSON看起来一模一样。三、根因fastjson 的循环引用检测$ref3.1 什么是 $reffastjson 在序列化时会记录已经序列化过的对象。如果同一个对象引用在结构里出现第二次它不会再展开而是写成一个引用标记{$ref:$[0].mtm}$ref路径语法$根对象$[0]根数组第 0 个元素$[0].mtm第 0 个元素的 mtm 字段它的本意是防止循环引用导致的无限递归StackOverflowError例如父子对象互相持有的场景。3.2 判定依据是「引用相同」而非「内容相同」关键点fastjson 用的是**对象身份同一个内存地址**来判重类似IdentityHashMap不是用equals()比内容。情况是否同一个引用会不会 $ref同一个 List 被多个字段引用共享 mtm是成立会两个不同对象内容一模一样独立克隆否不成立不会推论同一个对象引用 → 内容一定相同成立因为就是同一个对象。内容相同 → 是同一个对象不成立可能是内容巧合相同的独立对象。所以「内容相同但不是同一个实例」不会触发$ref不会出问题。3.3 为什么这次会踩坑共享 mtm 后多个HistoryPriceQuery的mtm指向同一个 List 实例。fastjson 序列化时[{key:0,mtm:[{material:82H803GJJP,key:0}]},// 第一次完整展开{key:1,mtm:{$ref:$[0].mtm}},// 第二次变成 $ref{key:2,mtm:{$ref:$[0].mtm}}// 第三次变成 $ref]WSO2 接口不认识$ref它是 fastjson 私有语法不是标准 JSON 语义解析畸形报文失败 → 请求报错。独立克隆版本里每个 mtm 都是不同对象没有重复引用不会出现$ref报文干净 → 成功。四、为什么「打印一样、发送却失败」这是最迷惑的一点原因在于两个 API 的差异JSON.toJSON(obj)先把对象转成一棵全新的 JSONObject/JSONArray 树转换过程把共享引用摊平成各自独立的节点再toString。此时已经没有「同一对象」了所以打印结果正常、看不出$ref。JSON.toJSONString(obj)直接序列化原始对象共享引用仍然存在 → 触发$ref。getHistoryPrice内部发请求时用的是toJSONString或等价的直接序列化所以才会带$ref。结论判断有没有$ref一定要看toJSONString的结果不能用toJSON。五、如何检测是否触发了 $ref方法 1直接打印 toJSONStringSystem.out.println(JSON.toJSONString(priceQuery));输出里出现{$ref:...}即触发。方法 2字符串搜 $refStringjsonJSON.toJSONString(priceQuery);booleanhasRefjson.contains($ref);System.out.println(包含 $ref hasRef);方法 3对比开/关检测的结果importcom.alibaba.fastjson.serializer.SerializerFeature;StringwithDetectJSON.toJSONString(priceQuery);// 默认开检测可能有 $refStringwithoutDetectJSON.toJSONString(priceQuery,SerializerFeature.DisableCircularReferenceDetect);// 关检测全展开System.out.println(两者是否不同 !withDetect.equals(withoutDetect));两者不同即说明默认序列化里存在$ref。六、解决方案方案说明建议独立克隆不共享引用每个对象各自持有独立实例从源头避免重复引用✅ 推荐关闭引用检测JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)需改到每个序列化点易漏⚠️ 谨慎全局关闭影响面大❌ 不建议本次采用独立克隆虽然多占一点内存但对外传输数据正确、稳定不用碰序列化配置是最省心的选择。七、经验总结对外传输尤其发给第三方接口的对象避免多个字段/元素共享同一个可序列化对象实例否则 fastjson 会用$ref表示重复引用导致对端解析失败。$ref只认同一实例不认equals内容相同。内容相同但不同实例是安全的。排查时用toJSONString看真实报文别用toJSON后者会把引用摊平掩盖问题。「省内存的共享」和「对外序列化的安全」有时是冲突的涉及序列化传输的场景优先保证隔离性独立实例。

相关新闻

迪奥720丝绒红棕,源头工厂敢接单的底线在哪?代工老板别被“大牌同源”忽悠了

迪奥720丝绒红棕,源头工厂敢接单的底线在哪?代工老板别被“大牌同源”忽悠了

最近好几个做私域团长的老朋友找我,开口就问:“能不能搞到跟某法系头部品牌720同款质感的红棕调口红?客户就要那个丝绒哑光、高折射率光泽的上唇体验。”我直接泼冷水:15元一支,连正经的合成酯和高折射率油脂都买不到&…

2026/7/28 10:11:38 阅读更多 →
开年第一个月,好几个做私域团长的老朋友打来电话,开口就问:迪奥720那款磁吸翻盖口红的包材,到底能不能做到“大牌同源”级别的公差?我直接回他们:别跟我聊“复刻”,咱们就聊车间里真金白银的包材定制和进货

开年第一个月,好几个做私域团长的老朋友打来电话,开口就问:迪奥720那款磁吸翻盖口红的包材,到底能不能做到“大牌同源”级别的公差?我直接回他们:别跟我聊“复刻”,咱们就聊车间里真金白银的包材定制和进货

做D家720同款磁吸翻盖口红,包材结构看似简单,但产线一开,全是工业细节。磁吸闭合是第一道生死关——普通铁氧体磁铁吸力仅约0.2Ncm,开合数次即松动;而正规代工厂必须采用钕磁铁,吸力稳定≥0.3Ncm&#xff0…

2026/7/26 0:39:05 阅读更多 →
Unity 程序员编曲第二天:当经典片头遇上失真吉他

Unity 程序员编曲第二天:当经典片头遇上失真吉他

Unity 程序员学编曲的第二天。上一期,我挑战了那首大家耳熟能详的《新闻联播》片头曲;这一期,继续在它的基础上进行改编,尝试把它变成一个摇滚风格的版本。熟悉的旋律配上更有力量的节奏,竟然也碰撞出了别样的味道。 U…

2026/7/27 4:23:17 阅读更多 →

最新新闻

负载均衡在APP开发中的运用的重要性

负载均衡在APP开发中的运用的重要性

在APP开发项目中,服务器架构是关系到整个系统的性能的关键因素。无论是自己买的服务器,还是用云服务器,负载均衡都是提高系统性能的主要方式。如果你是早期的云计算服务提供商,你可以使用一个单独的客户 web 服务器,为…

2026/7/28 20:07:02 阅读更多 →
Android APK签名冲突:从V1/V2签名原理到ADB彻底解决方案

Android APK签名冲突:从V1/V2签名原理到ADB彻底解决方案

1. 项目概述:签名冲突,Android开发者的“隐形杀手” 如果你在Android开发或测试过程中,遇到过“应用未安装”、“签名冲突”或者“INSTALL_FAILED_UPDATE_INCOMPATIBLE”这类错误,那么恭喜你,你正踩在一个几乎所有开发…

2026/7/28 20:07:02 阅读更多 →
APP开发初级产品经理常犯的错误

APP开发初级产品经理常犯的错误

在APP开发公司刚入行做产品经理,可能还不知道产品岗位具体是做什么。作为一名APP开发的产品经理,通常需要做的就是需求分析、原型图设计、需求文档的编写,需求的管理、开发的跟进等。APP开发的产品经理必须要有点儿技术底子的,运营…

2026/7/28 20:07:02 阅读更多 →
宠物电商APP开发如何帮助平台完善体制

宠物电商APP开发如何帮助平台完善体制

目前,很多人将养宠物作为自己的一种兴趣爱好,对此,以宠物电商APP开发为基础,能够实现一站式服务,推动行业整体向前发展。一、宠物电商APP开发概述宠物电商APP开发提供多方面的操作功能,包括:首页…

2026/7/28 20:07:02 阅读更多 →
跑步助手APP开发可以带来哪些便捷操作

跑步助手APP开发可以带来哪些便捷操作

一个健康的身体对于人们来说是很重要的,毕竟一切的拼搏和冲刺都需要健康,如果健康出现了问题,那么不论是学习、工作还是生活都会受到不同程度的影响。为了健康,也有不少人选择通过跑步这样的有氧运动来保持,而且跑步也…

2026/7/28 20:07:02 阅读更多 →
FastFlix:高效视频格式转换工具的技术解析与应用

FastFlix:高效视频格式转换工具的技术解析与应用

1. FastFlix:视频格式转换的终极解决方案作为一名长期处理视频内容的创作者,我深知格式转换这个看似简单的需求背后隐藏着多少痛点。不同平台对视频格式的要求各异,原始素材的编码方式五花八门,而传统转换工具要么速度慢如蜗牛&am…

2026/7/28 20:06:02 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻