You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2019/09/08 16:15:24 UTC
[johnzon] branch master updated: JOHNZON-274 ensure JsonPatch
respects requested path for arrays and objects
This is an automated email from the ASF dual-hosted git repository.
rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/johnzon.git
The following commit(s) were added to refs/heads/master by this push:
new e4d3684 JOHNZON-274 ensure JsonPatch respects requested path for arrays and objects
e4d3684 is described below
commit e4d3684269b37ece70143a68ebc50b346183307e
Author: Romain Manni-Bucau <rm...@apache.org>
AuthorDate: Sun Sep 8 18:15:14 2019 +0200
JOHNZON-274 ensure JsonPatch respects requested path for arrays and objects
---
.../org/apache/johnzon/core/JsonPointerImpl.java | 89 +++++++++++++---------
.../org/apache/johnzon/core/JsonPatchTest.java | 60 ++++++++++++---
2 files changed, 103 insertions(+), 46 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..89eed57 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
@@ -39,7 +39,6 @@ public class JsonPointerImpl implements JsonPointer {
private final JsonProvider provider;
private final String jsonPointer;
private final List<String> referenceTokens = new ArrayList<>();
- private final String lastReferenceToken;
private static final Pattern IS_NUMBER = Pattern.compile("\\d+");
/**
@@ -64,7 +63,6 @@ public class JsonPointerImpl implements JsonPointer {
for (String encodedReferenceToken : encodedReferenceTokens) {
referenceTokens.add(JsonPointerUtil.decode(encodedReferenceToken));
}
- lastReferenceToken = referenceTokens.get(referenceTokens.size() - 1);
}
/**
@@ -262,11 +260,10 @@ public class JsonPointerImpl implements JsonPointer {
* or if the reference is the target.
*/
public JsonStructure remove(JsonStructure target) {
- if (target instanceof JsonObject) {
- return remove((JsonObject) target);
- } else {
- return remove((JsonArray) target);
+ if (target.getValueType() == JsonValue.ValueType.OBJECT) {
+ return remove(target.asJsonObject());
}
+ return remove(target.asJsonArray());
}
/**
@@ -282,7 +279,7 @@ public class JsonPointerImpl implements JsonPointer {
public JsonObject remove(JsonObject target) {
validateRemove(target);
- return (JsonObject) remove(target, 1, referenceTokens.size() - 1);
+ return remove(target, 1).asJsonObject();
}
/**
@@ -298,13 +295,21 @@ public class JsonPointerImpl implements JsonPointer {
public JsonArray remove(JsonArray target) {
validateRemove(target);
- return (JsonArray) remove(target, 1, referenceTokens.size() - 1);
+ return remove(target, 1).asJsonArray();
}
String getJsonPointer() {
return jsonPointer;
}
+ @Override
+ public String toString() {
+ return "JsonPointerImpl{" +
+ "jsonPointer='" + jsonPointer + '\'' +
+ ", referenceTokens=" + referenceTokens +
+ '}';
+ }
+
private void validateAdd(JsonValue target) {
validateJsonPointer(target, referenceTokens.size() - 1);
}
@@ -356,12 +361,12 @@ public class JsonPointerImpl implements JsonPointer {
}
private JsonValue addInternal(JsonValue jsonValue, JsonValue newValue, List<String> currentPath) {
- if (jsonValue instanceof JsonObject) {
+ if (jsonValue.getValueType() == JsonValue.ValueType.OBJECT) {
JsonObject jsonObject = (JsonObject) jsonValue;
JsonObjectBuilder objectBuilder = provider.createObjectBuilder();
if (jsonObject.isEmpty() && isPositionToAdd(currentPath)) {
- objectBuilder.add(lastReferenceToken, newValue);
+ objectBuilder.add(referenceTokens.get(referenceTokens.size() - 1), newValue);
} else {
for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
@@ -370,18 +375,18 @@ public class JsonPointerImpl implements JsonPointer {
currentPath.remove(entry.getKey());
if (isPositionToAdd(currentPath)) {
- objectBuilder.add(lastReferenceToken, newValue);
+ objectBuilder.add(referenceTokens.get(referenceTokens.size() - 1), newValue);
}
}
}
return objectBuilder.build();
- } else if (jsonValue instanceof JsonArray) {
+ } else if (jsonValue.getValueType() == JsonValue.ValueType.ARRAY) {
JsonArray jsonArray = (JsonArray) jsonValue;
JsonArrayBuilder arrayBuilder = provider.createArrayBuilder();
int arrayIndex = -1;
if (isPositionToAdd(currentPath)) {
- arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, true);
+ arrayIndex = getArrayIndex(referenceTokens.get(referenceTokens.size() - 1), jsonArray, true);
}
int jsonArraySize = jsonArray.size();
@@ -408,36 +413,46 @@ 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) {
- if (jsonValue instanceof JsonObject) {
- JsonObject jsonObject = (JsonObject) jsonValue;
- JsonObjectBuilder objectBuilder = provider.createObjectBuilder();
+ private JsonValue remove(final JsonValue jsonValue, final int currentPosition) {
+ if (referenceTokens.size() <= currentPosition) { // unlikely
+ return jsonValue;
+ }
- for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
- if (currentPosition == referencePosition
- && lastReferenceToken.equals(entry.getKey())) {
+ final String token = referenceTokens.get(currentPosition);
+ if (jsonValue.getValueType() == JsonValue.ValueType.OBJECT) {
+ final JsonObject jsonObject = jsonValue.asJsonObject();
+ final JsonObjectBuilder objectBuilder = provider.createObjectBuilder();
+ for (final Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
+ final boolean matchesToken = token.equals(entry.getKey());
+ if (matchesToken && currentPosition == referenceTokens.size() - 1) {
continue;
}
- objectBuilder.add(entry.getKey(), remove(entry.getValue(), currentPosition + 1, referencePosition));
+ if (matchesToken) {
+ objectBuilder.add(
+ entry.getKey(),
+ remove(entry.getValue(), currentPosition + 1));
+ } else {
+ objectBuilder.add(entry.getKey(), entry.getValue());
+ }
}
return objectBuilder.build();
- } else if (jsonValue instanceof JsonArray) {
- JsonArray jsonArray = (JsonArray) jsonValue;
- JsonArrayBuilder arrayBuilder = provider.createArrayBuilder();
-
- int arrayIndex = -1;
- if (currentPosition == referencePosition && IS_NUMBER.matcher(lastReferenceToken).matches()) {
- arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, false);
- }
-
- int jsonArraySize = jsonArray.size();
- for (int i = 0; i < jsonArraySize; i++) {
- if (i == arrayIndex) {
- continue;
+ } else if (jsonValue.getValueType() == JsonValue.ValueType.ARRAY) {
+ final JsonArray jsonArray = jsonValue.asJsonArray();
+ if (IS_NUMBER.matcher(token).matches()) {
+ final JsonArrayBuilder arrayBuilder = provider.createArrayBuilder();
+ final int arrayIndex = getArrayIndex(token, jsonArray, false);
+ final int jsonArraySize = jsonArray.size();
+ for (int i = 0; i < jsonArraySize; i++) {
+ final boolean matchesIndex = i == arrayIndex;
+ if (matchesIndex && currentPosition != referenceTokens.size() - 1) {
+ arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1));
+ } else if (!matchesIndex) {
+ arrayBuilder.add(jsonArray.get(i));
+ }
}
- arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1, referencePosition));
- }
- return arrayBuilder.build();
+ return arrayBuilder.build();
+ } // else?
+ return jsonArray;
}
return jsonValue;
}
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..6d9b41e 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
@@ -29,12 +29,9 @@ import javax.json.JsonObject;
import javax.json.JsonPatch;
import javax.json.JsonStructure;
import javax.json.JsonValue;
-import javax.json.JsonWriter;
import javax.json.spi.JsonProvider;
import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -998,15 +995,60 @@ public class JsonPatchTest {
Assert.assertNotNull(patchedJsonObject);
}
-
- private static String toJsonString(JsonStructure value) {
- final Writer writer = new StringWriter();
- try (final JsonWriter jsonWriter = Json.createWriter(writer)) {
- jsonWriter.write(value);
+ @Test
+ public void testReplacingObjectAttribute() {
+ final JsonObject object = Json.createObjectBuilder()
+ .add("foo", Json.createObjectBuilder()
+ .add("baz", Json.createValue("1")))
+ .add("bar", Json.createObjectBuilder()
+ .add("baz", Json.createValue("2")))
+ .build();
+ final JsonPatchImpl patch = new JsonPatchImpl(
+ PROVIDER, new JsonPatchImpl.PatchValue(PROVIDER, JsonPatch.Operation.REPLACE,
+ "/bar/baz",
+ null,
+ Json.createValue("3")));
+ final JsonObject patched = patch.apply(object);
+ assertNotNull(patched);
+ assertNotSame(object, patched);
+ {
+ final JsonObject o = patched.getJsonObject("foo");
+ assertNotNull(o);
+ assertEquals(Json.createValue("1"), o.getJsonString("baz"));
+ }
+ {
+ final JsonObject o = patched.getJsonObject("bar");
+ assertNotNull(o);
+ assertEquals(Json.createValue("3"), o.getJsonString("baz"));
+ assertEquals("{\"foo\":{\"baz\":\"1\"},\"bar\":{\"baz\":\"3\"}}", toJsonString(patched));
}
- return writer.toString();
}
+ @Test
+ public void testReplacingArrayElementAttribute() {
+ final JsonObject object = Json.createObjectBuilder()
+ .add("foo", Json.createArrayBuilder()
+ .add(Json.createObjectBuilder().add("bar", Json.createValue("1")))
+ .add(Json.createObjectBuilder().add("bar", Json.createValue("2"))))
+ .build();
+ final JsonPatchImpl patch = new JsonPatchImpl(PROVIDER, new JsonPatchImpl.PatchValue(PROVIDER, JsonPatch.Operation.REPLACE,
+ "/foo/1/bar",
+ null,
+ Json.createValue("3")));
+ final JsonObject patched = patch.apply(object);
+ assertNotNull(patched);
+ assertNotSame(object, patched);
+ final JsonArray array = patched.getJsonArray("foo");
+ assertNotNull(array);
+ assertNotSame(object.getJsonArray("foo"), array);
+ assertEquals(2, array.size());
+ assertEquals(Json.createValue("3"), array.getJsonObject(1).getJsonString("bar"));
+ assertEquals(Json.createValue("1"), array.getJsonObject(0).getJsonString("bar"));
+ assertEquals("{\"foo\":[{\"bar\":\"1\"},{\"bar\":\"3\"}]}", toJsonString(patched));
+ }
+ private static String toJsonString(final JsonStructure value) {
+ return value.toString();
+ }
}