记录一次 JSONArray 引发的惨案
起因
开发接口时,用到了fastjson 的 JSONObject 和 JSONArray,使用同一个 JSONArray 进行不同字段的排序,输出会出现如下情况 {".nameArr[0]"}:
{"nameArr":[{"sex":"男","name":"One"}],"sexArr":[{"$ref":"$.nameArr[0]"}]}
分析
首先想到的是深拷贝和浅拷贝导致引用了同一个对象才会出现这个问题。尝试了使用深拷贝 .clone() ,但是问题并没有被解决。一次尝试一次错,一直尝试一直错0.0.....
真正原因: 查阅资料发现是因为使用FastJson的JSONArray类型作为返回数据,当像JSONArray对象中添加JSONObject对象,而JSONObject对象中包含相同的节点数据时,FastJson会防止返回数据栈溢出的问题,自动将JSONArray中相同的节点数据使用引用方式代替。
解决方案(禁用循环引用)
强大的 FastJson 为我们提供了相关的配置参数来禁用循环引用,示例代码如下:
JSONArray jsonArrayUserNum = JSONArray.parseArray(JSON.toJSONString(resultJsonArr, SerializerFeature.DisableCircularReferenceDetect));
流程:禁止循环引用-->转化为 json 字符串-->再降 json 串转为 JSONArray-->存入新的 JSONArray
个人理解(欢迎指正):就是变相的完成了一次深拷贝。
复现代码如下
用到的fastjson依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
SourceCode
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class MyReview {
public static void main(String[] args) {
JSONArray resultJsonArr = new JSONArray();
JSONObject itemOne = new JSONObject();
itemOne.put("name", "One");
itemOne.put("sex", "男");
resultJsonArr.add(itemOne);
JSONObject resultJson = new JSONObject();
resultJson.put("nameArr", resultJsonArr);
resultJson.put("sexArr", resultJsonArr);
System.out.println(resultJson);
System.out.println(resultJson.toString());
System.out.println(JSON.toJSONString(resultJson, SerializerFeature.DisableCircularReferenceDetect));
String a = "";
a.trim();
}
}
运行结果