fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[BUG] 嵌套结构序列化结果错误

Open SinguJ opened this issue 2 years ago • 4 comments

问题描述

对于嵌套结构的模型(例如树形结构模型),当超过 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>

SinguJ avatar Jun 28 '22 10:06 SinguJ

子元素仅有一个时不会出现该问题,超过 1 个时,从第二个开始都会变成 {"$ref":"$[0].children[0].children"}

SinguJ avatar Jun 28 '22 10:06 SinguJ

其他的字段不受影响

代码


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

SinguJ avatar Jun 28 '22 10:06 SinguJ

改成这样JSONArray.toJSONString(elements,SerializerFeature.DisableCircularReferenceDetect),应该就不会出现循环引用了

wsxe9988 avatar Jun 28 '22 11:06 wsxe9988

改成这样JSONArray.toJSONString(elements,SerializerFeature.DisableCircularReferenceDetect),应该就不会出现循环引用了

这样确实可以解决,但是最好还是对 Collections.emptyList() 增加默认支持吧。 Fastjson 1 是默认就可以的,如果从 Fastjson 1 升级到 2 就需要修改这部分代码了。

SinguJ avatar Jun 29 '22 03:06 SinguJ

https://github.com/alibaba/fastjson2/releases/tag/2.0.15 问题修复,请用新版本

wenshao avatar Oct 05 '22 06:10 wenshao