Skip to content

Commit 095fd76

Browse files
authored
fix: 修复 fastjson1 兼容层 JSONPath 连续写入失效问题 (#7697)
* fix: 修复 fastjson1 兼容层 JSONPath 连续写入失效问题 * refactor: 统一 fastjson1 兼容层 live-wrapper 适配 * test: 完善 fastjson1 live-wrapper 回归测试 * test: 补充 core JSONArray live-wrapper 回归测试 * test: 补充 JSONArray.get live-wrapper 回归测试
1 parent adbfb28 commit 095fd76

4 files changed

Lines changed: 102 additions & 2 deletions

File tree

fastjson1-compatible/src/main/java/com/alibaba/fastjson/JSON.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,6 +2318,22 @@ public static Object adaptResult(Object result) {
23182318
return adaptResult(result, 0);
23192319
}
23202320

2321+
/**
2322+
* Returns a live wrapper sharing state with the underlying fastjson2 container;
2323+
* mutations propagate to the parent. Use in {@code get()}-family accessors where
2324+
* JSONPath navigation must see writes. Use {@link #adaptResult(Object)} for
2325+
* independent snapshots.
2326+
*/
2327+
static Object adaptResultLive(Object result) {
2328+
if (result instanceof com.alibaba.fastjson2.JSONObject) {
2329+
return new JSONObject((com.alibaba.fastjson2.JSONObject) result);
2330+
}
2331+
if (result instanceof com.alibaba.fastjson2.JSONArray) {
2332+
return new JSONArray((com.alibaba.fastjson2.JSONArray) result);
2333+
}
2334+
return result;
2335+
}
2336+
23212337
private static Object adaptResult(Object result, int level) {
23222338
if (level > MAX_LEVEL) {
23232339
throw new JSONException("level too large : " + level);

fastjson1-compatible/src/main/java/com/alibaba/fastjson/JSONArray.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,8 @@ public boolean containsAll(Collection c) {
592592

593593
@Override
594594
public Object get(int index) {
595-
return adaptResult(list.get(index));
595+
Object value = list.get(index);
596+
return adaptResultLive(value);
596597
}
597598

598599
/**

fastjson1-compatible/src/main/java/com/alibaba/fastjson/JSONObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public Object get(Object key) {
127127
val = map.get(key.toString());
128128
}
129129

130-
return adaptResult(val);
130+
return adaptResultLive(val);
131131
}
132132

133133
public JSONObject getJSONObject(String key) {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.alibaba.fastjson.v2issues;
2+
3+
import com.alibaba.fastjson.JSONArray;
4+
import com.alibaba.fastjson.JSONObject;
5+
import com.alibaba.fastjson.JSONPath;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.util.concurrent.atomic.AtomicReference;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.junit.jupiter.api.Assertions.assertSame;
12+
13+
public class Issue7690 {
14+
@Test
15+
public void testSetFieldAfterAutoCreatingArrayElement() {
16+
JSONObject root = new JSONObject();
17+
18+
JSONObject item = new JSONObject();
19+
item.put("title", "1");
20+
item.put("value", "110");
21+
22+
JSONArray testArray = new JSONArray();
23+
testArray.add(item);
24+
root.put("test", testArray);
25+
26+
JSONPath.set(root, "$.test[1].title", 2);
27+
assertEquals(2, JSONPath.eval(root, "$.test[1].title"));
28+
29+
JSONPath.set(root, "$.test[1].value", 220);
30+
assertEquals(2, JSONPath.eval(root, "$.test[1].title"));
31+
assertEquals(220, JSONPath.eval(root, "$.test[1].value"));
32+
}
33+
34+
@Test
35+
public void testGetReturnsLiveWrapperForCoreJSONObject() {
36+
JSONObject root = new JSONObject();
37+
root.put("test", new com.alibaba.fastjson2.JSONObject());
38+
39+
JSONObject test = (JSONObject) root.get("test");
40+
test.put("value", 220);
41+
42+
assertEquals(220, JSONPath.eval(root, "$.test.value"));
43+
}
44+
45+
@Test
46+
public void testGetReturnsLiveWrapperForCoreJSONArray() {
47+
JSONObject root = new JSONObject();
48+
root.put("arr", new com.alibaba.fastjson2.JSONArray());
49+
50+
JSONArray arr = (JSONArray) root.get("arr");
51+
arr.add(220);
52+
53+
assertEquals(220, JSONPath.eval(root, "$.arr[0]"));
54+
}
55+
56+
@Test
57+
public void testArrayGetReturnsLiveWrapperForCoreJSONObject() {
58+
JSONArray arr = new JSONArray();
59+
arr.add(new com.alibaba.fastjson2.JSONObject());
60+
61+
JSONObject obj = (JSONObject) arr.get(0);
62+
obj.put("value", 42);
63+
64+
JSONObject obj2 = (JSONObject) arr.get(0);
65+
assertEquals(42, obj2.get("value"));
66+
}
67+
68+
@Test
69+
public void testLiveWrapperIterationExposesUnderlyingCoreNestedContainers() {
70+
JSONObject root = new JSONObject();
71+
JSONPath.set(root, "$.a.b.c", 1);
72+
73+
JSONObject a = (JSONObject) root.get("a");
74+
Object value = a.values().iterator().next();
75+
Object entryValue = a.entrySet().iterator().next().getValue();
76+
AtomicReference<Object> forEachValue = new AtomicReference<>();
77+
a.forEach((key, item) -> forEachValue.set(item));
78+
79+
assertEquals(com.alibaba.fastjson2.JSONObject.class, value.getClass());
80+
assertSame(value, entryValue);
81+
assertSame(value, forEachValue.get());
82+
}
83+
}

0 commit comments

Comments
 (0)