From 09921d291a7c685379c48bd139d94886f79c3c74 Mon Sep 17 00:00:00 2001 From: Jeff Hu Date: Sun, 8 Sep 2019 16:27:09 +0200 Subject: [PATCH] fix when JsonPatch removing, JsonObjects not on the path but with same name&level get removed. --- .../apache/johnzon/core/JsonPointerImpl.java | 20 ++++--- .../apache/johnzon/core/JsonPatchTest.java | 57 +++++++++++++++++++ 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java index 6cad8c2..b311d73 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java @@ -282,7 +282,7 @@ public class JsonPointerImpl implements JsonPointer { public JsonObject remove(JsonObject target) { validateRemove(target); - return (JsonObject) remove(target, 1, referenceTokens.size() - 1); + return (JsonObject) remove(target, 1, referenceTokens.size() - 1, true); } /** @@ -298,7 +298,7 @@ public class JsonPointerImpl implements JsonPointer { public JsonArray remove(JsonArray target) { validateRemove(target); - return (JsonArray) remove(target, 1, referenceTokens.size() - 1); + return (JsonArray) remove(target, 1, referenceTokens.size() - 1, true); } String getJsonPointer() { @@ -408,17 +408,20 @@ public class JsonPointerImpl implements JsonPointer { currentPath.get(currentPath.size() - 1).equals(referenceTokens.get(referenceTokens.size() - 2)); } - private JsonValue remove(JsonValue jsonValue, int currentPosition, int referencePosition) { + private JsonValue remove(JsonValue jsonValue, int currentPosition, int referencePosition, boolean onPath) { if (jsonValue instanceof JsonObject) { JsonObject jsonObject = (JsonObject) jsonValue; JsonObjectBuilder objectBuilder = provider.createObjectBuilder(); for (Map.Entry entry : jsonObject.entrySet()) { - if (currentPosition == referencePosition + boolean stillOnPath = onPath; + if (onPath && currentPosition == referencePosition && lastReferenceToken.equals(entry.getKey())) { continue; + } else if (onPath && !referenceTokens.get(currentPosition).equals(entry.getKey())) { + stillOnPath = false; } - objectBuilder.add(entry.getKey(), remove(entry.getValue(), currentPosition + 1, referencePosition)); + objectBuilder.add(entry.getKey(), remove(entry.getValue(), currentPosition + 1, referencePosition, stillOnPath)); } return objectBuilder.build(); } else if (jsonValue instanceof JsonArray) { @@ -426,16 +429,19 @@ public class JsonPointerImpl implements JsonPointer { JsonArrayBuilder arrayBuilder = provider.createArrayBuilder(); int arrayIndex = -1; - if (currentPosition == referencePosition && IS_NUMBER.matcher(lastReferenceToken).matches()) { + if (onPath && currentPosition == referencePosition && IS_NUMBER.matcher(lastReferenceToken).matches()) { arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, false); } int jsonArraySize = jsonArray.size(); for (int i = 0; i < jsonArraySize; i++) { + boolean stillOnPath = onPath; if (i == arrayIndex) { continue; + } else if (onPath && i != getArrayIndex(referenceTokens.get(currentPosition), jsonArray, false)) { + stillOnPath = false; } - arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1, referencePosition)); + arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1, referencePosition, stillOnPath)); } return arrayBuilder.build(); } diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java index e579e5b..03b820b 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java @@ -347,6 +347,63 @@ public class JsonPatchTest { assertEquals("{\"foo\":[\"bar\",\"boo\"]}", toJsonString(patched)); } + @Test + public void testReplacingObjectAttribute() { + + JsonObject object = Json.createObjectBuilder() + .add("foo", Json.createObjectBuilder() + .add("baz", new JsonStringImpl("1"))) + .add("bar", Json.createObjectBuilder() + .add("baz", new JsonStringImpl("2"))) + .build(); + + JsonPatchImpl patch = new JsonPatchImpl(PROVIDER, new JsonPatchImpl.PatchValue(PROVIDER, JsonPatch.Operation.REPLACE, + "/bar/baz", + null, + new JsonStringImpl("3"))); + + JsonObject patched = patch.apply(object); + assertNotNull(patched); + assertNotSame(object, patched); + + JsonObject o = patched.getJsonObject("foo"); + assertNotNull(o); + assertEquals(new JsonStringImpl("1"), o.getJsonString("baz")); + o = patched.getJsonObject("bar"); + assertNotNull(o); + assertEquals(new JsonStringImpl("3"), o.getJsonString("baz")); + + assertEquals("{\"foo\":{\"baz\":\"1\"},\"bar\":{\"baz\":\"3\"}}", toJsonString(patched)); + } + + @Test + public void testReplacingArrayElementAttribute() { + + JsonObject object = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("bar", new JsonStringImpl("1"))) + .add(Json.createObjectBuilder().add("bar", new JsonStringImpl("2")))) + .build(); + + JsonPatchImpl patch = new JsonPatchImpl(PROVIDER, new JsonPatchImpl.PatchValue(PROVIDER, JsonPatch.Operation.REPLACE, + "/foo/1/bar", + null, + new JsonStringImpl("3"))); + + JsonObject patched = patch.apply(object); + assertNotNull(patched); + assertNotSame(object, patched); + + JsonArray array = patched.getJsonArray("foo"); + assertNotNull(array); + assertNotSame(object.getJsonArray("foo"), array); + assertEquals(2, array.size()); + assertEquals(new JsonStringImpl("3"), array.getJsonObject(1).getJsonString("bar")); + assertEquals(new JsonStringImpl("1"), array.getJsonObject(0).getJsonString("bar")); + + assertEquals("{\"foo\":[{\"bar\":\"1\"},{\"bar\":\"3\"}]}", toJsonString(patched)); + } + @Test public void testReplacingArrayElementPlainArray() { -- 2.21.0.windows.1