fastjson字符串转JSON的$ref问题

2022年01月16日 阅读数:5
这篇文章主要向大家介绍fastjson字符串转JSON的$ref问题,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

先说结论:java

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

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

问题出现的背景:json

在开发过程当中,使用了第三方的拓扑图组件。组件生成图形的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没问题。code

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

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}}