alibaba / fastjson2

🚄 FASTJSON2 is a Java JSON library with excellent performance.
Apache License 2.0
3.7k stars 479 forks source link

[BUG] JSONArray直接调用add添加非JSON数据结构的自定义类对象后,getJSONObject会产生预期之外的行为 #2989

Open fwhdzh opened 3 days ago

fwhdzh commented 3 days ago

问题描述

JSONArray直接调用add添加非JSON数据结构的自定义类对象后,getJSONObject会产生预期之外的行为。具体来说,对于某个位置的元素,每次调用getJSONObject会产生一个新的JSONObject对象,对该对象修改并不会对JSONArray数组中的原对象产生影响。

这样的处理逻辑非常容易让人产生迷惑,我认为应该对其进行修复。比如修改代码逻辑使得多次调用getJSONObject时返回相同的对象(也是存储在JSONArray中的对象),或者完善JSONArray.add和JSONArray.getJSONObject的文档对这种行为提供必要的警告信息。

环境信息

重现步骤

可调用如下所示的单元测试代码复现此缺陷。

    @Data
    public static class ComplexStruc {
        String value;
        public ComplexStruc(String v) {
            this.value = v;
        }
    }

    @Test
    void testFastJson4() {
        List<ComplexStruc> list = new ArrayList<>();
        list.add(new ComplexStruc("v1"));
        JSONArray jsonArray = JSONArray.from(list);
        System.out.println(jsonArray.toJSONString());
        JSONObject object = jsonArray.getJSONObject(0);
        object.computeIfPresent("value", (k, v) -> "v4");
        System.out.println(jsonArray.toJSONString());
        assertEquals("v4", jsonArray.getJSONObject(0).getString("value"));

        JSONArray jsonArray2 = new JSONArray();
        JSONObject obj = JSONObject.from(new ComplexStruc("v1"));
        jsonArray2.add(obj);
        System.out.println(jsonArray2.toJSONString());
        obj.computeIfPresent("value", (k, v) -> "v4");
        System.out.println(jsonArray2.toJSONString());
        assertEquals("v4", jsonArray2.getJSONObject(0).getString("value"));

        JSONArray jsonArray3 = new JSONArray();
        jsonArray3.add(new ComplexStruc("v1"));
        System.out.println(jsonArray3.toJSONString());
        JSONObject obj2 = jsonArray3.getJSONObject(0);
        obj2.computeIfPresent("value", (k, v) -> "v4");
        System.out.println(jsonArray3.toJSONString());
        assertEquals("v4", jsonArray3.getJSONObject(0).getString("value"));
    }

运行testFastJson4单元测试,前两个assertEquals可以通过,而第三个assertEquals不能通过。

期待的正确结果

上述测试用例的第三个assertEquals可以通过,或是通过JSONArray.add和JSONArray.getJSONObject的API文档针对该行为对用户提供警告信息。

相关日志输出

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

报错信息

org.opentest4j.AssertionFailedError: expected: <v4> but was: <v1>

测试用例中通过System.out.println打印的信息

[{"value":"v1"}]
[{"value":"v4"}]
[{"value":"v1"}]
[{"value":"v4"}]
[{"value":"v1"}]
[{"value":"v1"}]

附加信息

麻烦开发人员确认这是否是一个缺陷。如果需要的话,我很乐意为这个问题提供一个PR。