在用FastJson对对象进行序列化时,发现出来的json字符串中始终存在"$ref",具体示例如下:
public String buildRiskQueryLogFastJson(BaseContext baseContext, Map> riskRejectMap) {
List riskQueryLogDOList = new ArrayList<>();
HashMap dimensionMap = new HashMap<>(baseContext.getDimensionInfoMap());
for (String uniqueKey : baseContext.getUniqueKeyList()) {
RiskQueryLogDO riskQueryLogDO = new RiskQueryLogDO();
riskQueryLogDO.setQueryType(baseContext.getQueryType());
riskQueryLogDO.setRiskCheckId(baseContext.getRiskCheckId());
riskQueryLogDO.setBizLine(baseContext.getBizLine());
riskQueryLogDO.setEventId(baseContext.getEventId());
riskQueryLogDO.setChannel(baseContext.getChannel());
riskQueryLogDO.setOrigin(baseContext.getOrigin());
riskQueryLogDO.setUniqueKey(uniqueKey);
if (riskRejectMap.containsKey(uniqueKey)) {
riskQueryLogDO.setRiskResult(DecisionCodeEnum.getFromName(riskRejectMap.get(uniqueKey).get(ContextKeyConstant.RISK_RESULT)).getCode());
} else {
riskQueryLogDO.setRiskResult(DecisionCodeEnum.PASS.getCode());
}
riskQueryLogDO.setDimensionData(dimensionMap);
riskQueryLogDOList.add(riskQueryLogDO);
}
Map> msgMap = new HashMap<>();
msgMap.put("data", riskQueryLogDOList);
return JSON.toJSONString(msgMap);
}
@Test
public void sendMessageTest(){BaseContext baseContext = new BaseContext();
Map dimensionInfoMap = new HashMap<>();
dimensionInfoMap.put(ContextKeyConstant.USER_ID, "110119120");
dimensionInfoMap.put(ContextKeyConstant.USER_TYPE, "2");
dimensionInfoMap.put(ContextKeyConstant.USER_ID_TYPE, "1");
List
结果是这样的:
文章图片
可以看到,对于一个对象,当其首次出现时,FastJson的序列化是正常工作的,但是当其重复出现时,就会序列化实现,变为对象的引用.可以想到,这一定是FastJson内部存在一些特殊逻辑,问题产生的原因在于FastJson存在循环/重复引用检测特性,并且该特性是缺省开启的。
实体转化为json字符串后出现了$ref字样的东西,这是因为在传输的数据中出现相同的对象时,fastjson默认开启引用检测将相同的对象写成引用的形式,引用是通过"$ref"来表示的。
引用 | 描述 |
---|---|
"$ref":".." | 上一级 |
"$ref":"@" | 当前对象,也就是自引用 |
"$ref":"$" | 根对象 |
"$ref":"$.children.0" | 基于路径的引用,相当于 root.getChildren().get(0) |
JSON.toJSONString(msgMap, SerializerFeature.DisableCircularReferenceDetect);
如果想要全局关闭该功能:
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
FastJson要这个特性干吗用?
fastjson默认对json序列化的时候进行循环引用的检测,从而避免了出现StackOverFlow异常。当序列化后的JSON传输到浏览器或者其他语言中,这些json解析器不支持循环引用,从而导致数据丢失。
疑问: 既然在很多场景下浏览器并不支持该功能,那么为甚么还要把这个功能设置为缺省开启呢?
原因在于,如果存在循环引用,很有可能会出现SOF异常,因此设计了循环引用检测的保护
【FastJson 序列化出现"$ref"问题】reference
https://juejin.cn/post/684490...
https://blog.csdn.net/fly9109...
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)