fastjson2
fastjson2 copied to clipboard
[BUG] 嵌套结构序列化结果错误
问题描述
对于嵌套结构的模型(例如树形结构模型),当超过 1 个叶子节点的子元素列表字段被赋值为 Collections.emptyList()
时,序列化结果将从第 2 个子元素开始输出错误的结果。
ps: 描述的不是很清楚,输出结果应该一目了然了。
环境信息
- OS信息: Windows 11 22000.739 x64 i5-1130G7 1.80GHz 16GB
- JDK信息: Orcale OpenJDK 1.8.0_271
- 版本信息:Fastjson2 2.0.8
重现步骤
简化后可以稳定复现的代码是这样的:
import com.alibaba.fastjson.JSONArray;
import org.junit.Test;
import java.util.*;
public class FastJsonTest {
@Test
public void test1 () {
Element child0 = new Element();
child0.setChildren(Collections.emptyList());
Element child1 = new Element();
child1.setChildren(Collections.emptyList());
List<Element> children = new ArrayList<>();
children.add(child0);
children.add(child1);
Element parent = new Element();
parent.setChildren(children);
List<Element> elements = new ArrayList<>();
elements.add(parent);
System.out.println(JSONArray.toJSONString(elements));
}
public static class Element {
private List<Element> children;
public List<Element> getChildren () {
return this.children;
}
public void setChildren (List<Element> children) {
this.children = children;
}
}
}
期待的正确结果
[
{
"children": [
{
"children": []
},
{
"children": []
}
]
}
]
相关日志输出
原始输出
[{"children":[{"children":[]},{{"$ref":"$[0].children[0].children"}}]}]
手动格式化
[
{
"children": [
{
"children": []
},
{
{"$ref":"$[0].children[0].children"}
}
]
}
]
附加信息
Fastjson 包是从 Maven 资源库上更新的,pom.xml 配置为:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.8</version>
</dependency>
子元素仅有一个时不会出现该问题,超过 1 个时,从第二个开始都会变成 {"$ref":"$[0].children[0].children"}
其他的字段不受影响
代码
public class FastJsonTest {
@Test
public void test1 () {
Element child0 = new Element();
child0.setKey("A"); // 新增行
child0.setChildren(Collections.emptyList());
Element child1 = new Element();
child1.setKey("B"); // 新增行
child1.setChildren(Collections.emptyList());
// 新增块
Element child2 = new Element();
child2.setKey("C");
child2.setChildren(Collections.emptyList());
// 新增块 - 结束
List<Element> children = new ArrayList<>();
children.add(child0);
children.add(child1);
children.add(child2); // 新增行
Element parent = new Element();
parent.setKey("D"); // 新增行
parent.setChildren(children);
List<Element> elements = new ArrayList<>();
elements.add(parent);
System.out.println(JSONArray.toJSONString(elements));
}
public static class Element {
private String key; // 新增行
/** 子节点集合 **/
private List<Element> children;
// 新增块
public String getKey () {
return key;
}
public void setKey (String key) {
this.key = key;
}
// 新增块 - 结束
public List<Element> getChildren () {
return this.children;
}
public void setChildren (List<Element> children) {
this.children = children;
}
}
}
输出:
[{"children":[{"children":[],"key":"A"},{{"$ref":"$[0].children[0].children"}"key":"B"},{{"$ref":"$[0].children[0].children"}"key":"C"}],"key":"D"}]
改成这样JSONArray.toJSONString(elements,SerializerFeature.DisableCircularReferenceDetect),应该就不会出现循环引用了
改成这样JSONArray.toJSONString(elements,SerializerFeature.DisableCircularReferenceDetect),应该就不会出现循环引用了
这样确实可以解决,但是最好还是对 Collections.emptyList()
增加默认支持吧。
Fastjson 1 是默认就可以的,如果从 Fastjson 1 升级到 2 就需要修改这部分代码了。
https://github.com/alibaba/fastjson2/releases/tag/2.0.15 问题修复,请用新版本