diff --git a/json-smart/src/main/java/net/minidev/json/JSONObject.java b/json-smart/src/main/java/net/minidev/json/JSONObject.java index 21d3f89..8a0fcfc 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONObject.java +++ b/json-smart/src/main/java/net/minidev/json/JSONObject.java @@ -197,18 +197,27 @@ public void writeJSONString(Appendable out, JSONStyle compression) throws IOExce } public void merge(Object o2) { - merge(this, o2); + merge(this, o2, false); } - protected static JSONObject merge(JSONObject o1, Object o2) { + /** + * merge two JSONObject with overwrite or not + * overwrite = false will not overwrite existing key + * overwrite = true will overwrite the value with o2 of existing key + */ + public void merge(Object o2, boolean overwrite) { + merge(this, o2, overwrite); + } + + protected static JSONObject merge(JSONObject o1, Object o2, boolean overwrite) { if (o2 == null) return o1; if (o2 instanceof JSONObject) - return merge(o1, (JSONObject) o2); + return merge(o1, (JSONObject) o2, overwrite); throw new RuntimeException("JSON merge can not merge JSONObject with " + o2.getClass()); } - private static JSONObject merge(JSONObject o1, JSONObject o2) { + private static JSONObject merge(JSONObject o1, JSONObject o2, boolean overwrite) { if (o2 == null) return o1; for (String key : o1.keySet()) { @@ -221,13 +230,18 @@ private static JSONObject merge(JSONObject o1, JSONObject o2) { continue; } if (value1 instanceof JSONObject) { - o1.put(key, merge((JSONObject) value1, value2)); + o1.put(key, merge((JSONObject) value1, value2, overwrite)); continue; } if (value1.equals(value2)) continue; - if (value1.getClass() .equals(value2.getClass())) + if (value1.getClass().equals(value2.getClass())) { + if (overwrite) { + o1.put(key, value2); + continue; + } throw new RuntimeException("JSON merge can not merge two " + value1.getClass().getName() + " Object together"); + } throw new RuntimeException("JSON merge can not merge " + value1.getClass().getName() + " with " + value2.getClass().getName()); } for (String key : o2.keySet()) { diff --git a/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java b/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java new file mode 100644 index 0000000..0507f88 --- /dev/null +++ b/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java @@ -0,0 +1,178 @@ +package net.minidev.json.test; + +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class JSONObjectTest { + + @Test + void mergeIntegerFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", 1); + Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", 2); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge will fail + Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", 101); + jsonObject1.merge(jsonObject2); + }); + + Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.Integer Object together"); + } + + @Test + void mergeStringFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", "v2"); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge will fail + Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", "vNew2"); + jsonObject1.merge(jsonObject2); + System.out.println(jsonObject1.toJSONString()); + }); + + Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); + } + + @Test + void mergeJsonObjectFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", jsonObject1); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); + + // replace with new value by JSONObject merge will fail + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", jsonObject3); + Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); + + Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { + jsonObject4.merge(jsonObject2); + }); + + Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); + } + + @Test + void mergeJsonArraySuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", "v2"); + + JSONArray jsonArray1 = new JSONArray(); + jsonArray1.add(jsonObject1); + jsonArray1.add(jsonObject2); + Assertions.assertEquals("[{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray1.toJSONString()); + + // replace with new value by JSONObject merge will fail + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", "vNew2"); + + JSONArray jsonArray2 = new JSONArray(); + jsonArray2.add(jsonObject3); + jsonArray2.add(jsonObject4); + Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"}]", jsonArray2.toJSONString()); + + jsonArray2.merge(jsonArray1); + Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"},{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray2.toJSONString()); + } + + @Test + void mergeIntegerWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", 1); + Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", 2); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge with override success + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", 101); + jsonObject1.merge(jsonObject2, true); + Assertions.assertEquals("{\"k1\":101,\"k2\":2}", jsonObject1.toJSONString()); + } + + @Test + void mergeStringWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", "v2"); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge with override success + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", "vNew2"); + jsonObject1.merge(jsonObject2, true); + Assertions.assertEquals("{\"k1\":\"vNew2\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + } + + @Test + void mergeJsonObjectWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", jsonObject1); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); + + // JSONObject merge will overwrite jsonObject3 by jsonObject2 + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", jsonObject3); + Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); + + jsonObject4.merge(jsonObject2, true); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject4.toJSONString()); + } +} \ No newline at end of file