兼容包 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
补充说明
- 原生
com.alibaba.fastjson2.JSONPath + 原生 JSONObject 无此问题,说明 bug 在兼容包层。
- 即使将兼容包的
JSONObject 传入原生 com.alibaba.fastjson2.JSONPath.set,也会出现同样的 null 问题,说明兼容包类型与原生 API 混用时也存在兼容缺口。
- 直接用
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 创建对象)
兼容包
com.alibaba.fastjson.JSONPath.set越界创建元素后二次 set 不同字段不生效环境
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/无效果)。复现步骤
预期行为
第二次
JSONPath.set(root, "$.test[1].value", 220)后,test[1]应包含{"title":2,"value":220}。实际输出
补充说明
com.alibaba.fastjson2.JSONPath+ 原生JSONObject无此问题,说明 bug 在兼容包层。JSONObject传入原生com.alibaba.fastjson2.JSONPath.set,也会出现同样的 null 问题,说明兼容包类型与原生 API 混用时也存在兼容缺口。JSONObject.put("value", 220)操作已存在的元素可以正常写入,说明元素本身状态正确,是JSONPath.set的路径解析/定位逻辑有问题。临时绕过