fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[BUG]反序列化为JSONobject存在$ref引用,使用SerializerFeature.DisableCircularReferenceDetect会存在循环引用,栈溢出问题,生产环境不适用

Open zhangshuanying opened this issue 3 months ago • 6 comments

问题描述

简要描述您碰到的问题。

环境信息

请填写以下信息:

  • OS信息: [e.g.:CentOS 8.4.2105 4Core 3.10GHz 16 GB]
  • JDK信息: [e.g.:Openjdk 1.8.0_312]
  • 版本信息:[e.g.:Fastjson2 2.x.x]

重现步骤

如何操作可以重现该问题:

  1. 使用 xxx.xxx 方法
  2. 输入 ... 数据
  3. 出现 ... 错误
//可在此输入示例代码

期待的正确结果

对您期望发生的结果进行清晰简洁的描述。

相关日志输出

请复制并粘贴任何相关的日志输出。

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

zhangshuanying avatar Sep 22 '25 07:09 zhangshuanying

能提供一下复现问题的测试用例吗?

jujn avatar Sep 22 '25 07:09 jujn

能够提供一下恢复现有问题的测试示例吗?

@Test
    public void testSetString() {
        Person person = new Person("Alice");
        Department department = new Department("Tech");
        department.getMembers().add(person);
        department.getMembers().add(person);
        String jsonStringWithRef = JSON.toJSONString(department);

        System.out.println("JSON with $ref:");
        System.out.println(jsonStringWithRef);

        JSONObject jsonObject = JSON.parseObject(jsonStringWithRef);
        System.out.println("--------1");
        System.out.println(jsonObject);

        String jsonStringWithRef1 = JSON.toJSONString(department,SerializerFeature.DisableCircularReferenceDetect);

        System.out.println("JSON with $ref1:");
        System.out.println(jsonStringWithRef1);

        JSONObject jsonObject1 = JSON.parseObject(jsonStringWithRef1);
        System.out.println("--------2");
        System.out.println(jsonObject1);

    }

    @Data
    class Person {
        private String name;

        // getters and setters
        public Person(String name) {
            this.name = name;
        }
    }

    @Data
    class Department {
        private String name;
        private List<Person> members;

        // getters and setters
        public Department(String name) {
            this.name = name;
            this.members = new ArrayList<>();
        }
    }
JSON with $ref:
{"members":[{"name":"Alice"},{"$ref":"$.members[0]"}],"name":"Tech"}
--------1
{"members":[{"name":"Alice"},{"$ref":"$.members[0]"}],"name":"Tech"}
JSON with $ref1:
{"members":[{"name":"Alice"},{"name":"Alice"}],"name":"Tech"}
--------2
{"members":[{"name":"Alice"},{"name":"Alice"}],"name":"Tech"}

String jsonStringWithRef1 = JSON.toJSONString(department,SerializerFeature.DisableCircularReferenceDetect); 虽然解决了这个问题,但是会引发新的问题,循环引用,栈溢出。代码看下一贴

zhangshuanying avatar Sep 22 '25 07:09 zhangshuanying

能够提供一下恢复现有问题的测试示例吗?

@Test
    public void testSetString() {
        Person person = new Person("Alice");
        Department department = new Department("Tech");
        person.setDepartment(department);
        department.getMembers().add(person);
        department.getMembers().add(person);
        String jsonStringWithRef = JSON.toJSONString(department);

        System.out.println("JSON with $ref:");
        System.out.println(jsonStringWithRef);

        JSONObject jsonObject = JSON.parseObject(jsonStringWithRef);
        System.out.println("--------1");
        System.out.println(jsonObject);

        String jsonStringWithRef1 = JSON.toJSONString(department,SerializerFeature.DisableCircularReferenceDetect);

        System.out.println("JSON with $ref1:");
        System.out.println(jsonStringWithRef1);

        JSONObject jsonObject1 = JSON.parseObject(jsonStringWithRef1);
        System.out.println("--------2");
        System.out.println(jsonObject1);

    }

    @Data
    class Person {
        private String name;
        private Department department;
        // getters and setters
        public Person(String name) {
            this.name = name;
        }
    }

    @Data
    class Department {
        private String name;
        private List<Person> members;

        // getters and setters
        public Department(String name) {
            this.name = name;
            this.members = new ArrayList<>();
        }
    }
JSON with $ref:
{"members":[{"department":{"$ref":"$"},"name":"Alice"},{"$ref":"$.members[0]"}],"name":"Tech"}
--------1
{"members":[{"name":"Alice","department":{"$ref":"$"}},{"$ref":"$.members[0]"}],"name":"Tech"}

java.lang.StackOverflowError
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.writeReference(JavaBeanSerializer.java:548)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:185)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:160)
	at com.alibaba.fastjson.serializer.ListSerializer.write(ListSerializer.java:135)
	at com.alibaba.fastjson.serializer.FieldSerializer.writeValue(FieldSerializer.java:324)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:454)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:160)
	at com.alibaba.fastjson.serializer.FieldSerializer.writeValue(FieldSerializer.java:324)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:454)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:160)

zhangshuanying avatar Sep 22 '25 07:09 zhangshuanying

您使用的是兼容包吗?SerializerFeature 是fastjson1.x的组件

jujn avatar Sep 22 '25 08:09 jujn

您使用的是兼容包吗?SerializerFeature 是fastjson1.x的组件

提单的位置放错了。使用的fastjson1.x。

zhangshuanying avatar Sep 22 '25 08:09 zhangshuanying

您使用的是兼容包吗?SerializerFeature 是fastjson1.x的组件

提单的位置放错了。使用的fastjson1.x。

1.x 现在已经停止维护了,可以尝试使用兼容包,或升级为2.x(或者尝试使用1.x的最后版本1.2.83)

jujn avatar Sep 22 '25 08:09 jujn