Skip to content

兼容包 com.alibaba.fastjson.JSONPath.set 越界创建元素后二次 set 不同字段不生效 #7690

Description

@chcodex

兼容包 com.alibaba.fastjson.JSONPath.set 越界创建元素后二次 set 不同字段不生效

环境

  • fastjson 兼容包: com.alibaba:fastjson:2.0.62(或 com.alibaba.:fastjson:2.0.62
  • 底层: com.alibaba.fastjson2:fastjson2:2.0.62

问题描述

JSONPath.set 因为越界自动扩展数组并创建 JSONObject 后,对该元素的其他字段再次调用 JSONPath.set 不会生效,值丢失(表现为 null/无效果)。

复现步骤

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;

public class Reproduce {
    public static void main(String[] args) {
        JSONObject root = new JSONObject();
        JSONObject item = new JSONObject();
        item.put("title", "1");
        item.put("value", "110");
        JSONArray arr = new JSONArray();
        arr.add(item);
        root.put("test", arr);

        // 第一次 set:越界创建 test[1]
        JSONPath.set(root, "$.test[1].title", 2);
        System.out.println(JSON.toJSONString(root));
        // 输出: {"test":[{"title":"1","value":"110"},{"title":2}]}   ✅ 正确

        // 第二次 set:在 test[1] 上追加 value 字段
        JSONPath.set(root, "$.test[1].value", 220);
        System.out.println(JSON.toJSONString(root));
        // 输出: {"test":[{"title":"1","value":"110"},{"title":2}]}   ❌ value=220 丢失

        Object v = JSONPath.eval(root, "$.test[1].value");
        System.out.println(v);
        // 输出: null  ❌ 应为 220
    }
}

预期行为

第二次 JSONPath.set(root, "$.test[1].value", 220) 后,test[1] 应包含 {"title":2,"value":220}

实际输出

{"test":[{"title":"1","value":"110"},{"title":2}]}
{"test":[{"title":"1","value":"110"},{"title":2}]}
null

补充说明

  1. 原生 com.alibaba.fastjson2.JSONPath + 原生 JSONObject 无此问题,说明 bug 在兼容包层。
  2. 即使将兼容包的 JSONObject 传入原生 com.alibaba.fastjson2.JSONPath.set,也会出现同样的 null 问题,说明兼容包类型与原生 API 混用时也存在兼容缺口。
  3. 直接用 JSONObject.put("value", 220) 操作已存在的元素可以正常写入,说明元素本身状态正确,是 JSONPath.set 的路径解析/定位逻辑有问题。

临时绕过

// 方案 1:先 eval 拿到对象再 put
JSONObject elem = (JSONObject) JSONPath.eval(root, "$.test[1]");
elem.put("value", 220);

// 方案 2:使用原生 fastjson2 API
// com.alibaba.fastjson2.JSONPath.set(root, "$.test[1].value", 220);
// (需使用 com.alibaba.fastjson2.JSONObject 创建对象)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions