Skip to content

Commit e122f1f

Browse files
authored
Merge pull request #238 from caimo/master
fix JSONObject.merge blocks overwriting (#175)
2 parents 36849c8 + c13db00 commit e122f1f

File tree

2 files changed

+198
-6
lines changed

2 files changed

+198
-6
lines changed

json-smart/src/main/java/net/minidev/json/JSONObject.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,18 +197,27 @@ public void writeJSONString(Appendable out, JSONStyle compression) throws IOExce
197197
}
198198

199199
public void merge(Object o2) {
200-
merge(this, o2);
200+
merge(this, o2, false);
201201
}
202202

203-
protected static JSONObject merge(JSONObject o1, Object o2) {
203+
/**
204+
* merge two JSONObject with overwrite or not
205+
* overwrite = false will not overwrite existing key
206+
* overwrite = true will overwrite the value with o2 of existing key
207+
*/
208+
public void merge(Object o2, boolean overwrite) {
209+
merge(this, o2, overwrite);
210+
}
211+
212+
protected static JSONObject merge(JSONObject o1, Object o2, boolean overwrite) {
204213
if (o2 == null)
205214
return o1;
206215
if (o2 instanceof JSONObject)
207-
return merge(o1, (JSONObject) o2);
216+
return merge(o1, (JSONObject) o2, overwrite);
208217
throw new RuntimeException("JSON merge can not merge JSONObject with " + o2.getClass());
209218
}
210219

211-
private static JSONObject merge(JSONObject o1, JSONObject o2) {
220+
private static JSONObject merge(JSONObject o1, JSONObject o2, boolean overwrite) {
212221
if (o2 == null)
213222
return o1;
214223
for (String key : o1.keySet()) {
@@ -221,13 +230,18 @@ private static JSONObject merge(JSONObject o1, JSONObject o2) {
221230
continue;
222231
}
223232
if (value1 instanceof JSONObject) {
224-
o1.put(key, merge((JSONObject) value1, value2));
233+
o1.put(key, merge((JSONObject) value1, value2, overwrite));
225234
continue;
226235
}
227236
if (value1.equals(value2))
228237
continue;
229-
if (value1.getClass() .equals(value2.getClass()))
238+
if (value1.getClass().equals(value2.getClass())) {
239+
if (overwrite) {
240+
o1.put(key, value2);
241+
continue;
242+
}
230243
throw new RuntimeException("JSON merge can not merge two " + value1.getClass().getName() + " Object together");
244+
}
231245
throw new RuntimeException("JSON merge can not merge " + value1.getClass().getName() + " with " + value2.getClass().getName());
232246
}
233247
for (String key : o2.keySet()) {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package net.minidev.json.test;
2+
3+
import net.minidev.json.JSONArray;
4+
import net.minidev.json.JSONObject;
5+
import org.junit.jupiter.api.Assertions;
6+
import org.junit.jupiter.api.Test;
7+
8+
class JSONObjectTest {
9+
10+
@Test
11+
void mergeIntegerFailed() {
12+
JSONObject jsonObject1 = new JSONObject();
13+
jsonObject1.appendField("k1", 1);
14+
Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString());
15+
16+
// replace with new value by Map merge
17+
jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue);
18+
Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString());
19+
20+
JSONObject jsonObject3 = new JSONObject();
21+
jsonObject3.appendField("k2", 2);
22+
jsonObject1.merge(jsonObject3);
23+
Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString());
24+
25+
// replace with new value by JSONObject merge will fail
26+
Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
27+
JSONObject jsonObject2 = new JSONObject();
28+
jsonObject2.appendField("k1", 101);
29+
jsonObject1.merge(jsonObject2);
30+
});
31+
32+
Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.Integer Object together");
33+
}
34+
35+
@Test
36+
void mergeStringFailed() {
37+
JSONObject jsonObject1 = new JSONObject();
38+
jsonObject1.appendField("k1", "v1");
39+
Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString());
40+
41+
// replace with new value by Map merge
42+
jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue);
43+
Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString());
44+
45+
JSONObject jsonObject3 = new JSONObject();
46+
jsonObject3.appendField("k2", "v2");
47+
jsonObject1.merge(jsonObject3);
48+
Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString());
49+
50+
// replace with new value by JSONObject merge will fail
51+
Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
52+
JSONObject jsonObject2 = new JSONObject();
53+
jsonObject2.appendField("k1", "vNew2");
54+
jsonObject1.merge(jsonObject2);
55+
System.out.println(jsonObject1.toJSONString());
56+
});
57+
58+
Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together");
59+
}
60+
61+
@Test
62+
void mergeJsonObjectFailed() {
63+
JSONObject jsonObject1 = new JSONObject();
64+
jsonObject1.appendField("k1", "v1");
65+
Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString());
66+
67+
JSONObject jsonObject2 = new JSONObject();
68+
jsonObject2.appendField("k2", jsonObject1);
69+
Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString());
70+
71+
// replace with new value by JSONObject merge will fail
72+
JSONObject jsonObject3 = new JSONObject();
73+
jsonObject3.appendField("k1", "vNew1");
74+
75+
JSONObject jsonObject4 = new JSONObject();
76+
jsonObject4.appendField("k2", jsonObject3);
77+
Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString());
78+
79+
Exception exception = Assertions.assertThrows(RuntimeException.class, () -> {
80+
jsonObject4.merge(jsonObject2);
81+
});
82+
83+
Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together");
84+
}
85+
86+
@Test
87+
void mergeJsonArraySuccess() {
88+
JSONObject jsonObject1 = new JSONObject();
89+
jsonObject1.appendField("k1", "v1");
90+
JSONObject jsonObject2 = new JSONObject();
91+
jsonObject2.appendField("k2", "v2");
92+
93+
JSONArray jsonArray1 = new JSONArray();
94+
jsonArray1.add(jsonObject1);
95+
jsonArray1.add(jsonObject2);
96+
Assertions.assertEquals("[{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray1.toJSONString());
97+
98+
// replace with new value by JSONObject merge will fail
99+
JSONObject jsonObject3 = new JSONObject();
100+
jsonObject3.appendField("k1", "vNew1");
101+
JSONObject jsonObject4 = new JSONObject();
102+
jsonObject4.appendField("k2", "vNew2");
103+
104+
JSONArray jsonArray2 = new JSONArray();
105+
jsonArray2.add(jsonObject3);
106+
jsonArray2.add(jsonObject4);
107+
Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"}]", jsonArray2.toJSONString());
108+
109+
jsonArray2.merge(jsonArray1);
110+
Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"},{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray2.toJSONString());
111+
}
112+
113+
@Test
114+
void mergeIntegerWithOverwriteSuccess() {
115+
JSONObject jsonObject1 = new JSONObject();
116+
jsonObject1.appendField("k1", 1);
117+
Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString());
118+
119+
// replace with new value by Map merge
120+
jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue);
121+
Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString());
122+
123+
JSONObject jsonObject3 = new JSONObject();
124+
jsonObject3.appendField("k2", 2);
125+
jsonObject1.merge(jsonObject3);
126+
Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString());
127+
128+
// replace with new value by JSONObject merge with override success
129+
JSONObject jsonObject2 = new JSONObject();
130+
jsonObject2.appendField("k1", 101);
131+
jsonObject1.merge(jsonObject2, true);
132+
Assertions.assertEquals("{\"k1\":101,\"k2\":2}", jsonObject1.toJSONString());
133+
}
134+
135+
@Test
136+
void mergeStringWithOverwriteSuccess() {
137+
JSONObject jsonObject1 = new JSONObject();
138+
jsonObject1.appendField("k1", "v1");
139+
Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString());
140+
141+
// replace with new value by Map merge
142+
jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue);
143+
Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString());
144+
145+
JSONObject jsonObject3 = new JSONObject();
146+
jsonObject3.appendField("k2", "v2");
147+
jsonObject1.merge(jsonObject3);
148+
Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString());
149+
150+
// replace with new value by JSONObject merge with override success
151+
JSONObject jsonObject2 = new JSONObject();
152+
jsonObject2.appendField("k1", "vNew2");
153+
jsonObject1.merge(jsonObject2, true);
154+
Assertions.assertEquals("{\"k1\":\"vNew2\",\"k2\":\"v2\"}", jsonObject1.toJSONString());
155+
}
156+
157+
@Test
158+
void mergeJsonObjectWithOverwriteSuccess() {
159+
JSONObject jsonObject1 = new JSONObject();
160+
jsonObject1.appendField("k1", "v1");
161+
Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString());
162+
163+
JSONObject jsonObject2 = new JSONObject();
164+
jsonObject2.appendField("k2", jsonObject1);
165+
Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString());
166+
167+
// JSONObject merge will overwrite jsonObject3 by jsonObject2
168+
JSONObject jsonObject3 = new JSONObject();
169+
jsonObject3.appendField("k1", "vNew1");
170+
171+
JSONObject jsonObject4 = new JSONObject();
172+
jsonObject4.appendField("k2", jsonObject3);
173+
Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString());
174+
175+
jsonObject4.merge(jsonObject2, true);
176+
Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject4.toJSONString());
177+
}
178+
}

0 commit comments

Comments
 (0)