You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by st...@apache.org on 2017/02/27 20:35:10 UTC
johnzon git commit: JOHNZON-103 add tests and basic impl for
JsonPatch Diff handling
Repository: johnzon
Updated Branches:
refs/heads/master 61a130e3e -> 2940f6e13
JOHNZON-103 add tests and basic impl for JsonPatch Diff handling
Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/2940f6e1
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/2940f6e1
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/2940f6e1
Branch: refs/heads/master
Commit: 2940f6e1309080f37a70ac538275d80b9d5abe19
Parents: 61a130e
Author: Mark Struberg <st...@apache.org>
Authored: Mon Feb 27 21:34:34 2017 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Mon Feb 27 21:34:34 2017 +0100
----------------------------------------------------------------------
.../org/apache/johnzon/core/JsonPatchDiff.java | 88 ++++++++++++++++++
.../apache/johnzon/core/JsonProviderImpl.java | 5 ++
.../johnzon/core/JsonMergeBatchBuilderTest.java | 20 ++---
.../apache/johnzon/core/JsonPatchDiffTest.java | 93 ++++++++++++++++++++
.../org/apache/johnzon/core/JsonPatchTest.java | 39 --------
5 files changed, 196 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
new file mode 100644
index 0000000..81a7bf2
--- /dev/null
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.core;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonPatch;
+import javax.json.JsonPatchBuilder;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+
+/**
+ * Create a diff from a source and target JsonStructure
+ */
+public class JsonPatchDiff {
+
+ private final JsonStructure source;
+ private final JsonStructure target;
+
+ public JsonPatchDiff(JsonStructure source, JsonStructure target) {
+ this.source = source;
+ this.target = target;
+ }
+
+ public JsonPatch calculateDiff() {
+ JsonPatchBuilder patchBuilder = new JsonPatchBuilderImpl();
+
+ diff(patchBuilder, "/", source, target);
+
+ return patchBuilder.build();
+ }
+
+ private void diff(JsonPatchBuilder patchBuilder, String basePath, JsonStructure source, JsonStructure target) {
+ if (source instanceof JsonObject && target instanceof JsonObject) {
+ // handle JsonObjects
+ diffJsonObjects(patchBuilder, basePath, (JsonObject) source, (JsonObject) target);
+ } else if (source instanceof JsonArray && target instanceof JsonArray) {
+ // handle JsonArray
+ //X TODO
+ throw new UnsupportedOperationException("not yet implemented.");
+ } else {
+ throw new UnsupportedOperationException("not yet implemented.");
+ }
+ }
+
+ private void diffJsonObjects(JsonPatchBuilder patchBuilder, String basePath, JsonObject source, JsonObject target) {
+ Set<Map.Entry<String, JsonValue>> sourceEntries = source.entrySet();
+
+ for (Map.Entry<String, JsonValue> sourceEntry : sourceEntries) {
+ String attributeName = sourceEntry.getKey();
+ if (target.containsKey(attributeName)) {
+ JsonValue targetValue = ((JsonObject) target).get(attributeName);
+ if (!sourceEntry.getValue().equals(targetValue)) {
+ // replace the original value
+ patchBuilder.replace(basePath + attributeName, targetValue);
+ }
+ } else {
+ // the value got removed
+ patchBuilder.remove(basePath + attributeName);
+ }
+ }
+
+ Set<Map.Entry<String, JsonValue>> targetEntries = target.entrySet();
+ for (Map.Entry<String, JsonValue> targetEntry : targetEntries) {
+ if (!source.containsKey(targetEntry.getKey())) {
+ patchBuilder.add(basePath + targetEntry.getKey(), targetEntry.getValue());
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
index 354158a..9df37da 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
@@ -364,6 +364,11 @@ public class JsonProviderImpl extends JsonProvider implements Serializable {
return createPatchBuilder(array).build();
}
+ @Override
+ public JsonPatch createDiff(JsonStructure source, JsonStructure target) {
+ return new JsonPatchDiff(source, target).calculateDiff();
+ }
+
//X TODO add missing methods
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
index 141ed9d..b5be087 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
@@ -16,20 +16,20 @@
*/
package org.apache.johnzon.core;
-import javax.json.spi.JsonProvider;
-public class JsonMergeBatchBuilderTest {
+import org.junit.Test;
- private static final String[][] TEST_CASES = new String[][]{
- {
- "{\"a\":\"b\"}",
- "{\"a\":\"c\"}",
- "{\"a\":\"c\"}"
- }
- };
+public class JsonMergeBatchBuilderTest {
+ @Test
public void testSimpleMergePatch() {
- JsonProvider provider = JsonProvider.provider();
+ // {"a":"xa","b","xb"}
+ String source = "{\"a\":\"xa\",\"b\",\"xb\"}";
+
+ // {"b":"bNew","c":"xc"}
+ String patch = "{\"b\":\"bNew\",\"c\":\"xc\"}";
+
+ //X TODO Json.createMergePatch();
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
new file mode 100644
index 0000000..3462a19
--- /dev/null
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.core;
+
+import java.io.StringReader;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonPatch;
+import javax.json.JsonValue;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JsonPatchDiffTest {
+
+ @Test
+ public void testAddDiff() {
+ // {"a":"xa"}
+ String jsonA = "{\"a\":\"xa\"}";
+
+ // {"a":"xa","b":"xb"}
+ String jsonB = "{\"a\":\"xa\",\"b\":\"xb\"}";
+
+ // this results in 1 diff operations:
+ // adding "b"
+ JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
+ Json.createReader(new StringReader(jsonB)).readObject());
+ Assert.assertNotNull(jsonPatch);
+ JsonArray patchOperations = jsonPatch.toJsonArray();
+ Assert.assertNotNull(patchOperations);
+ Assert.assertEquals(1, patchOperations.size());
+ containsOperation(patchOperations, JsonPatch.Operation.ADD, "/b", "xb");
+ }
+
+ @Test
+ @Ignore //X TODO reinhard take over ;)
+ public void testComplexDiff() {
+ // {"a":"xa","b":2,"c":{"d":"xd"},"e":[1,2,3]}
+ String jsonA = "{\"a\":\"xa\",\"b\":2,\"c\":{\"d\":\"xd\"},\"e\":[1,2,3]}";
+
+ // {"a":"xa","c":{"d":"xd", "d2":"xd2"},"e":[1,3],"f":"xe"}
+ String jsonB = "{\"a\":\"xa\",\"c\":{\"d\":\"xd\", \"d2\":\"xd2\"},\"e\":[1,3],\"f\":\"xe\"}";
+
+ // this results in 4 diff operations:
+ // removing b, adding d2, removing 2 from e, adding f
+ JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
+ Json.createReader(new StringReader(jsonB)).readObject());
+ Assert.assertNotNull(jsonPatch);
+ JsonArray patchOperations = jsonPatch.toJsonArray();
+ Assert.assertNotNull(patchOperations);
+ Assert.assertEquals(4, patchOperations.size());
+ containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/b", null);
+ containsOperation(patchOperations, JsonPatch.Operation.ADD, "/c/d2", "xd2");
+ containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/e/2", null);
+ containsOperation(patchOperations, JsonPatch.Operation.ADD, "/f", "xe");
+ }
+
+ private void containsOperation(JsonArray patchOperations, JsonPatch.Operation patchOperation,
+ String jsonPointer, String value) {
+ for (JsonValue operation : patchOperations) {
+ if (operation instanceof JsonObject &&
+ patchOperation.operationName().equalsIgnoreCase(((JsonObject) operation).getString("op"))) {
+ Assert.assertEquals(jsonPointer, ((JsonObject) operation).getString("path"));
+
+ if (value != null) {
+ Assert.assertEquals(value, ((JsonObject) operation).getString("value"));
+ }
+
+ return;
+ }
+ }
+ Assert.fail("patchOperations does not contain " + patchOperation + " " + jsonPointer);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
----------------------------------------------------------------------
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 dc54c0c..6c96329 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
@@ -969,45 +969,6 @@ public class JsonPatchTest {
}
- //X @Test disabled for now
- //X TODO implement the diff logic!
- public void testDiff() {
- // {"a":"xa","b":2,"c":{"d":"xd"},"e":[1,2,3]}
- String jsonA = "{\"a\":\"xa\",\"b\":2,\"c\":{\"d\":\"xd\"},\"e\":[1,2,3]}";
-
- // {"a":"xa","c":{"d":"xd", "d2":"xd2"},"e":[1,3],"f":"xe"}
- String jsonB = "{\"a\":\"xa\",\"c\":{\"d\":\"xd\", \"d2\":\"xd2\"},\"e\":[1,3],\"f\":\"xe\"}";
-
- // this results in 4 diff operations:
- // removing b, adding d2, removing 2 from e, adding f
- JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
- Json.createReader(new StringReader(jsonB)).readObject());
- Assert.assertNotNull(jsonPatch);
- JsonArray patchOperations = jsonPatch.toJsonArray();
- Assert.assertNotNull(patchOperations);
- Assert.assertEquals(4, patchOperations.size());
- containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/b", null);
- containsOperation(patchOperations, JsonPatch.Operation.ADD, "/c/d2", "xd2");
- containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/e/2", null);
- containsOperation(patchOperations, JsonPatch.Operation.ADD, "/f", "xe");
- }
-
- private void containsOperation(JsonArray patchOperations, JsonPatch.Operation patchOperation,
- String jsonPointer, String value) {
- for (JsonValue operation : patchOperations) {
- if (operation instanceof JsonObject &&
- patchOperation.operationName().equalsIgnoreCase(((JsonObject) operation).getString("op"))) {
- Assert.assertEquals(jsonPointer, ((JsonObject) operation).getString("path"));
-
- if (value != null) {
- Assert.assertEquals(value, ((JsonObject) operation).getString("value"));
- }
- }
- }
- Assert.fail("patchOperations does not contain " + patchOperation + " " + jsonPointer);
- }
-
-
private static String toJsonString(JsonStructure value) {
StringWriter writer = new StringWriter();
Json.createWriter(writer).write(value);