您的位置:首页 > Web前端 > JavaScript

fastjson字符串转JSON的$ref问题

2022-01-15 16:01 951 查看 https://www.cnblogs.com/lichla

先说结论:

fastjson在把对象转换成字符串的时候,如果遇到相同的对象的时候,默认开启引用检测将相同的对象写成引用的形式。

官网文档:https://github.com/alibaba/fastjson/wiki

问题出现的背景:

在开发过程中,使用了第三方的拓扑图组件。组件生成图形的json字符串在利用 fastjson 转换成 JSON 对象的时候报错如下所示:

Exception in thread "main" com.alibaba.fastjson.JSONException: illegal ref, int

后来定位到如下的字符串解析的时候会出错:

public class test {
public static void main(String[] args) {
String str1 = "{\"$position\":{\"$ref\":21}}";
String str2 = "{\"position\":{\"ref\":21}}";
JSONObject json = JSONObject.parseObject(str1);
}
}

解析str2没问题,解析str1报错

Exception in thread "main" com.alibaba.fastjson.JSONException: illegal ref, int

刚开始判断是$符号是特殊符号导致,所以去掉后解析str2没问题。

后来又测试下去掉第一个$

String str1 = "{\"position\":{\"$ref\":21}}";

还是报错:Exception in thread "main" com.alibaba.fastjson.JSONException: illegal ref, int

那么问题出现在第二个

$ref
上了。那么怀疑$ref 就好像保留字段一样,不能使用,于是修改为

String str1 = "{\"position\":{\"$reff\":21}}";

那么调用

JSONObject.parseObject(str1);
果然就正常了。

查阅官网资料:fastjson支持循环引用,并且是缺省打开的。

如果有相同的对象,那么 fastjson 会默认开启引用模式。

语法 描述
{"$ref":"$"} 引用根对象
{"$ref":"@"} 引用自己
{"$ref":".."} 引用父对象
{"$ref":"../.."} 引用父对象的父对象
{"$ref":"$.members[0].reportTo"} 基于路径的引用

官网还给出了说明:

当序列化后的JSON传输到浏览器或者其他语言中,这些json解析器不支持循环引用,从而导致数据丢失。你可以关闭fastjson的循环引用支持。关闭引用检测,还能够提升序列化时的性能。

全局配置关闭

JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();

非全局关闭

JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);

综上,我们的字符串中包括"$ref",fastjson 认为这是引用模式,但是引用的值又是不正确的,导致出错。

解决方式上面说了两种,一种全局,一种非全局的。

我们采用非全局的,那么下面的代码就是正确✅的了

public class test {
public static void main(String[] args) {
String str1 = "{\"$position\":{\"$reff\":21}}";
JSONObject json = JSONObject.parseObject(str1, Feature.DisableCircularReferenceDetect);
System.out.println(json);
}
}
结果:
{"$position":{"$reff":21}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: