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 34a8607 JOHNZON-304 Json.createDiff does not handle properly arrays overflow (more elements in target than source) + minor toString/cache values enhancements (useful for debug purposes) 34a8607 is described below commit 34a860746a7da9316feddf84f5ccc8dc085cbd46 Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Mon Apr 13 16:57:20 2020 +0200 JOHNZON-304 Json.createDiff does not handle properly arrays overflow (more elements in target than source) + minor toString/cache values enhancements (useful for debug purposes) --- .../org/apache/johnzon/core/JsonArrayImpl.java | 3 + .../org/apache/johnzon/core/JsonObjectImpl.java | 3 + .../org/apache/johnzon/core/JsonPatchDiff.java | 15 +--- .../org/apache/johnzon/core/JsonPatchImpl.java | 95 +++++++++++++++------- .../org/apache/johnzon/core/JsonPatchDiffTest.java | 19 +++++ 5 files changed, 94 insertions(+), 41 deletions(-) diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java index 7f87069..d05cfbf 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java @@ -163,6 +163,9 @@ class JsonArrayImpl extends AbstractList<JsonValue> implements JsonArray, Serial @Override public String toString() { + if (unmodifieableBackingList.isEmpty()) { + return "[]"; + } final StringWriter writer = new StringWriter(); try (final JsonGenerator generator = new JsonGeneratorImpl(writer, provider, false)) { generator.writeStartArray(); diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java index 03d65fe..4e45f08 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java @@ -143,6 +143,9 @@ final class JsonObjectImpl extends AbstractMap<String, JsonValue> implements Jso @Override public String toString() { + if (unmodifieableBackingMap.isEmpty()) { + return "{}"; + } final StringWriter writer = new StringWriter(); try (final JsonGenerator generator = new JsonGeneratorImpl(writer, provider, false)) { generator.writeStartObject(); 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 index 8610184..29577f0 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java @@ -61,19 +61,16 @@ class JsonPatchDiff extends DiffBase { private void diffJsonArray(JsonPatchBuilder patchBuilder, String basePath, JsonArray source, JsonArray target) { for (int i = 0; i < source.size(); i++) { - JsonValue sourceValue = source.get(i); - + final JsonValue sourceValue = source.get(i); if (target.size() <= i) { patchBuilder.remove(basePath + i); continue; } - diff(patchBuilder, basePath + i, sourceValue, target.get(i)); } if (target.size() > source.size()) { - - for (int i = target.size() - source.size(); i < target.size(); i++) { + for (int i = source.size(); i < target.size(); i++) { patchBuilder.add(basePath + i, target.get(i)); } } @@ -81,8 +78,7 @@ class JsonPatchDiff extends DiffBase { } private void diffJsonObjects(JsonPatchBuilder patchBuilder, String basePath, JsonObject source, JsonObject target) { - - for (Map.Entry<String, JsonValue> sourceEntry : source.entrySet()) { + for (final Map.Entry<String, JsonValue> sourceEntry : source.entrySet()) { String attributeName = sourceEntry.getKey(); if (target.containsKey(attributeName)) { @@ -93,13 +89,10 @@ class JsonPatchDiff extends DiffBase { } } - for (Map.Entry<String, JsonValue> targetEntry : target.entrySet()) { + for (final Map.Entry<String, JsonValue> targetEntry : target.entrySet()) { if (!source.containsKey(targetEntry.getKey())) { patchBuilder.add(basePath + JsonPointerUtil.encode(targetEntry.getKey()), targetEntry.getValue()); } } - } - - } diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java index ec3109d..91bb436 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java @@ -38,6 +38,7 @@ class JsonPatchImpl implements JsonPatch { private final JsonProvider provider; private final List<PatchValue> patches; + private volatile JsonArray json; JsonPatchImpl(final JsonProvider provider, final PatchValue... patches) { this(provider, Arrays.asList(patches)); @@ -118,16 +119,30 @@ class JsonPatchImpl implements JsonPatch { @Override public JsonArray toJsonArray() { - - JsonArrayBuilder builder = provider.createArrayBuilder(); - for (PatchValue patch : patches) { - builder.add(patch.toJson()); + if (patches.isEmpty()) { + return JsonValue.EMPTY_JSON_ARRAY; } - - return builder.build(); + if (json == null) { + synchronized (this) { + if (json == null) { + final JsonArrayBuilder builder = provider.createArrayBuilder(); + for (final PatchValue patch : patches) { + builder.add(patch.toJson()); + } + json = builder.build(); + } + } + } + return json; } - + @Override + public String toString() { + if (patches.isEmpty()) { + return "[]"; + } + return toJsonArray().toString(); + } static class PatchValue { private final JsonProvider provider; @@ -136,6 +151,10 @@ class JsonPatchImpl implements JsonPatch { private final JsonPointerImpl from; private final JsonValue value; + private volatile String str; + private volatile JsonObject json; + private volatile Integer hash; + PatchValue(final JsonProvider provider, final JsonPatch.Operation operation, final String path, @@ -181,38 +200,54 @@ class JsonPatchImpl implements JsonPatch { @Override public int hashCode() { - int result = operation.hashCode(); - result = 31 * result + path.hashCode(); - result = 31 * result + (from != null ? from.hashCode() : 0); - result = 31 * result + (value != null ? value.hashCode() : 0); - return result; + if (hash == null) { + synchronized (this) { + if (hash == null) { + int result = operation.hashCode(); + result = 31 * result + path.hashCode(); + result = 31 * result + (from != null ? from.hashCode() : 0); + result = 31 * result + (value != null ? value.hashCode() : 0); + hash = result; + } + } + } + return hash; } @Override public String toString() { - return "{" + - "op: " + operation + - ", path: " + path + - ", from: " + from + - ", value: " + value + - '}'; + if (str == null) { + synchronized (this) { + if (str == null) { + str = "{op: " + operation + ", path: " + path + ", from: " + from + ", value: " + value + '}'; + } + } + } + return str; } JsonObject toJson() { - JsonObjectBuilder builder = provider.createObjectBuilder() - .add("op", operation.name().toLowerCase()) - .add("path", path.getJsonPointer()); - - if (from != null) { - builder.add("from", from.getJsonPointer()); - } - - if (value != null) { - builder.add("value", value); + if (json == null) { + synchronized (this) { + if (json == null) { + JsonObjectBuilder builder = provider.createObjectBuilder() + .add("op", operation.name().toLowerCase()) + .add("path", path.getJsonPointer()); + + if (from != null) { + builder.add("from", from.getJsonPointer()); + } + + if (value != null) { + builder.add("value", value); + } + + json = builder.build(); + } + } } - - return builder.build(); + return json; } } } 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 index 51bada2..d591b98 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java @@ -32,6 +32,25 @@ import org.junit.Ignore; import org.junit.Test; public class JsonPatchDiffTest { + @Test + public void fromEmptyArray() { + final JsonObject from = Json.createObjectBuilder().add("testEmpty", JsonValue.EMPTY_JSON_ARRAY).build(); + final JsonObject to = Json.createObjectBuilder() + .add("testEmpty", Json.createArrayBuilder().add("something")) + .build(); + final JsonPatch diff = Json.createDiff(from, to); + assertEquals("[{\"op\":\"add\",\"path\":\"/testEmpty/0\",\"value\":\"something\"}]", diff.toString()); + } + + @Test + public void toEmptyArray() { + final JsonObject from = Json.createObjectBuilder() + .add("testEmpty", Json.createArrayBuilder().add("something")) + .build(); + final JsonObject to = Json.createObjectBuilder().add("testEmpty", JsonValue.EMPTY_JSON_ARRAY).build(); + final JsonPatch diff = Json.createDiff(from, to); + assertEquals("[{\"op\":\"remove\",\"path\":\"/testEmpty/0\"}]", diff.toString()); + } @Test public void testAddDiff() {