博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FastJson 序列化出现"$ref"问题研究
阅读量:6894 次
发布时间:2019-06-27

本文共 1751 字,大约阅读时间需要 5 分钟。

今天在测试微信公众号创建自定义菜单时,需要向微信的接口发送一段嵌套的json数据,在用FastJson对对象进行序列化时,发现出来的json字符串中始终存在"$ref",具体示例如下:

Map
cbtMap = new HashMap<>(); cbtMap.put("key", "image"); cbtMap.put("name", "回复图片"); cbtMap.put("type","click"); JSONObject cbtJson = new JSONObject(cbtMap); Map
vbtMap = new HashMap<>(); vbtMap.put("url", "http://www.cuiyongzhi.com"); vbtMap.put("name", "博客"); vbtMap.put("type","view"); JSONObject vbtJson = new JSONObject(vbtMap); JSONArray subButton=new JSONArray(); subButton.add(cbtJson); subButton.add(vbtJson); JSONObject buttonOne=new JSONObject(); buttonOne.put("name", "菜单"); buttonOne.put("sub_button", subButton); JSONArray button=new JSONArray(); button.add(vbtJson); button.add(buttonOne); button.add(cbtJson); JSONObject menujson=new JSONObject(); menujson.put("button", button); System.out.println(menujson.toJSONString());复制代码

出来的结果是这样的:

可以看到,对于一个对象,当其首次出现时,FastJson的序列化是正常工作的,但是当其重复出现时,就会序列化实现,变为对象的引用.可以想到,这一定是FastJson内部存在一些特殊逻辑,于是上网查了查资料,问题产生的原因在于FastJson存在循环/重复引用检测特性,并且该特性是缺省开启的

想要解决这个问题,非常简单,只需要将原来的menujson.toJSONString()改为如下代码:

// 禁用FastJson循环引用检测功能(非全局)JSON.toJSONString(menujson, SerializerFeature.DisableCircularReferenceDetect);复制代码

如果想要全局关闭该功能:

JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();复制代码

关闭该功能还会提高FastJson的性能哦

问题很快解决,但是不禁会思考: FastJson要这个特性干吗用?

fastjson默认对json序列化的时候进行循环引用的检测,从而避免了出现StackOverFlow异常。当序列化后的JSON传输到浏览器或者其他语言中,这些json解析器不支持循环引用,从而导致数据丢失。

疑问: 既然在很多场景下浏览器并不支持该功能,那么为甚么还要把这个功能设置为缺省开启呢?

原因在于,如果存在循环引用,很有可能会出现SOF异常,因此设计了循环引用检测的保护

转载于:https://juejin.im/post/5cbad0e0f265da0375169e67

你可能感兴趣的文章
js操作cookie
查看>>
[AutoCars(一)]自动驾驶汽车概述(上)
查看>>
jquery基础研究学习【HTML】
查看>>
几个C# Visual Studio编码技巧
查看>>
sql数据库各个版本清除日志
查看>>
jQuery扩展两类函数(对象调用,静态调用)
查看>>
nofollow标签使用方法
查看>>
sqlite实现新闻收藏和取消收藏
查看>>
Unity中的基础光照
查看>>
Final发布——视频博客
查看>>
SqlHelper类
查看>>
服务器端控件Button会自动刷新页面
查看>>
Sass函数:Sass Maps的函数-map-get($map,$key)
查看>>
HDU 1230 火星A+B
查看>>
C# foreach 为什么循环使用Foreach 效率要高
查看>>
oracle创建透明网关出现的问题
查看>>
对象和类
查看>>
分布式事务
查看>>
udp,select超时和recvfrom收不到数据原因
查看>>
将任意程序(如.bat文件)作为Windows服务运行
查看>>