Implemented JsonPointer add, replace and remove methods
Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/cc830c64 Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/cc830c64 Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/cc830c64 Branch: refs/heads/master Commit: cc830c64a4e6a175a02d13ad2ccf5140401530df Parents: 45faea0 Author: Armin Hasler <[email protected]> Authored: Mon Nov 14 10:09:22 2016 +0100 Committer: Mark Struberg <[email protected]> Committed: Tue Nov 22 21:28:49 2016 +0100 ---------------------------------------------------------------------- .../org/apache/johnzon/core/JsonPointer.java | 310 ++++++++++---- .../apache/johnzon/core/JsonPointerTest.java | 419 ++++++++++++++++++- 2 files changed, 647 insertions(+), 82 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/johnzon/blob/cc830c64/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java index af228be..ca942ef 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java @@ -18,11 +18,17 @@ */ package org.apache.johnzon.core; +import javax.json.Json; import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; import javax.json.JsonException; import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; import javax.json.JsonStructure; import javax.json.JsonValue; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * <p>This class is an immutable representation of a JSON Pointer as specified in @@ -49,7 +55,8 @@ import javax.json.JsonValue; public class JsonPointer { private final String jsonPointer; - private final String[] referenceTokens; + private final List<String> referenceTokens = new ArrayList<String>(); + private final String lastReferenceToken; /** * Constructs and initializes a JsonPointer. @@ -63,11 +70,16 @@ public class JsonPointer { throw new NullPointerException("jsonPointer must not be null"); } if (!jsonPointer.equals("") && !jsonPointer.startsWith("/")) { - throw new JsonException("A non-empty JSON pointer must begin with a '/'"); + throw new JsonException("A non-empty JsonPointer string must begin with a '/'"); } this.jsonPointer = jsonPointer; - referenceTokens = jsonPointer.split("/", -1); + String[] encodedReferenceTokens = jsonPointer.split("/", -1); + + for (String encodedReferenceToken : encodedReferenceTokens) { + referenceTokens.add(JsonPointerUtil.decode(encodedReferenceToken)); + } + lastReferenceToken = referenceTokens.get(referenceTokens.size() - 1); } /** @@ -113,43 +125,14 @@ public class JsonPointer { if (target == null) { throw new NullPointerException("target must not be null"); } - - if (jsonPointer.equals("")) { + if (isEmptyJsonPointer()) { return target; } JsonValue jsonValue = target; - - for (int i = 1; i < referenceTokens.length; i++) { - String decodedReferenceToken = JsonPointerUtil.decode(referenceTokens[i]); - - if (jsonValue instanceof JsonObject) { - JsonObject jsonObject = (JsonObject) jsonValue; - jsonValue = jsonObject.get(decodedReferenceToken); - - if (jsonValue == null) { - throw new JsonException("The JsonObject " + jsonObject + " contains no value for token " + decodedReferenceToken); - } - } else if (jsonValue instanceof JsonArray) { - JsonArray jsonArray = (JsonArray) jsonValue; - - try { - int index = Integer.parseInt(decodedReferenceToken); - if (index >= jsonArray.size()) { - throw new JsonException("The JsonArray " + jsonArray + " contains no element for index " + index); - } - if (decodedReferenceToken.startsWith("0") && decodedReferenceToken.length() > 1) { - throw new JsonException("The token " + decodedReferenceToken + " with leading zeros is not allowed to reference an element of a JsonArray"); - } - - jsonValue = jsonArray.get(index); - } catch (NumberFormatException e) { - throw new JsonException("The token " + decodedReferenceToken + " for the JsonArray " + jsonArray + " is not a number", e); - } - } - + for (int i = 1; i < referenceTokens.size(); i++) { + jsonValue = getValue(jsonValue, referenceTokens.get(i), i, referenceTokens.size() - 1); } - return jsonValue; } @@ -179,35 +162,19 @@ public class JsonPointer { * or if the pointer contains references to non-existing objects or arrays. */ public JsonStructure add(JsonStructure target, JsonValue value) { - return null; - } - - /** - * Replaces the value at the referenced location in the specified - * {@code target} with the specified {@code value}. - * - * @param target the target referenced by this {@code JsonPointer} - * @param value the value to be stored at the referenced location - * @return the transformed {@code target} after the value is replaced. - * @throws NullPointerException if {@code target} is {@code null} - * @throws JsonException if the referenced value does not exist, - * or if the reference is the target. - */ - public JsonStructure replace(JsonStructure target, JsonValue value) { - return null; - } + validateAdd(target); + if (isEmptyJsonPointer()) { + if (value.getClass() != target.getClass()) { + throw new JsonException("The value must have the same type as the target"); + } + return (JsonStructure) value; + } - /** - * Removes the value at the reference location in the specified {@code target} - * - * @param target the target referenced by this {@code JsonPointer} - * @return the transformed {@code target} after the value is removed. - * @throws NullPointerException if {@code target} is {@code null} - * @throws JsonException if the referenced value does not exist, - * or if the reference is the target. - */ - public JsonStructure remove(JsonStructure target) { - return null; + if (target instanceof JsonObject) { + return add((JsonObject) target, value); + } else { + return add((JsonArray) target, value); + } } /** @@ -224,7 +191,9 @@ public class JsonPointer { * @see #add(JsonStructure, JsonValue) */ public JsonObject add(JsonObject target, JsonValue value) { - return (JsonObject) this.add((JsonStructure) target, value); + validateAdd(target); + + return (JsonObject) add(target, 1, referenceTokens.size() - 1, value); } /** @@ -241,7 +210,28 @@ public class JsonPointer { * @see #add(JsonStructure, JsonValue) */ public JsonArray add(JsonArray target, JsonValue value) { - return (JsonArray) this.add((JsonStructure) target, value); + validateAdd(target); + + return (JsonArray) add(target, 1, referenceTokens.size() - 1, value); + } + + /** + * Replaces the value at the referenced location in the specified + * {@code target} with the specified {@code value}. + * + * @param target the target referenced by this {@code JsonPointer} + * @param value the value to be stored at the referenced location + * @return the transformed {@code target} after the value is replaced. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * or if the reference is the target. + */ + public JsonStructure replace(JsonStructure target, JsonValue value) { + if (target instanceof JsonObject) { + return replace((JsonObject) target, value); + } else { + return replace((JsonArray) target, value); + } } /** @@ -253,11 +243,10 @@ public class JsonPointer { * @throws NullPointerException if {@code target} is {@code null} * @throws JsonException if the referenced value does not exist, * or if the reference is the target. - * {@code target} with the specified {@code value}. * @see #replace(JsonStructure, JsonValue) */ public JsonObject replace(JsonObject target, JsonValue value) { - return (JsonObject) this.replace((JsonStructure) target, value); + return add(remove(target), value); } /** @@ -269,11 +258,27 @@ public class JsonPointer { * @throws NullPointerException if {@code target} is {@code null} * @throws JsonException if the referenced value does not exist, * or if the reference is the target. - * {@code target} with the specified {@code value}. * @see #replace(JsonStructure, JsonValue) */ public JsonArray replace(JsonArray target, JsonValue value) { - return (JsonArray) this.replace((JsonStructure) target, value); + return add(remove(target), value); + } + + /** + * Removes the value at the reference location in the specified {@code target} + * + * @param target the target referenced by this {@code JsonPointer} + * @return the transformed {@code target} after the value is removed. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * 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); + } } /** @@ -287,7 +292,9 @@ public class JsonPointer { * @see #remove(JsonStructure) */ public JsonObject remove(JsonObject target) { - return (JsonObject) this.remove((JsonStructure) target); + validateRemove(target); + + return (JsonObject) remove(target, 1, referenceTokens.size() - 1); } /** @@ -301,8 +308,169 @@ public class JsonPointer { * @see #remove(JsonStructure) */ public JsonArray remove(JsonArray target) { - return (JsonArray) this.remove((JsonStructure) target); + validateRemove(target); + + return (JsonArray) remove(target, 1, referenceTokens.size() - 1); + } + + private void validateAdd(JsonValue target) { + validateJsonPointer(target, referenceTokens.size() - 1); } + private void validateRemove(JsonValue target) { + validateJsonPointer(target, referenceTokens.size()); + if (isEmptyJsonPointer()) { + throw new JsonException("The reference must not be the target"); + } + } + + private boolean isEmptyJsonPointer() { + return jsonPointer.equals(""); + } + + private JsonValue getValue(JsonValue jsonValue, String referenceToken, int currentPosition, int referencePosition) { + if (jsonValue instanceof JsonObject) { + JsonObject jsonObject = (JsonObject) jsonValue; + jsonValue = jsonObject.get(referenceToken); + + if (jsonValue != null) { + return jsonValue; + } + throw new JsonException("'" + jsonObject + "' contains no value for name '" + referenceToken + "'"); + } else if (jsonValue instanceof JsonArray) { + validateArrayIndex(referenceToken); + + try { + JsonArray jsonArray = (JsonArray) jsonValue; + int arrayIndex = Integer.parseInt(referenceToken); + validateArraySize(jsonArray, arrayIndex, jsonArray.size()); + return jsonArray.get(arrayIndex); + } catch (NumberFormatException e) { + throw new JsonException("'" + referenceToken + "' is no valid array index", e); + } + } else { + if (currentPosition != referencePosition) { + return jsonValue; + } + throw new JsonException("'" + jsonValue + "' contains no element for '" + referenceToken + "'"); + } + } + + private JsonValue add(JsonValue jsonValue, int currentPosition, int referencePosition, JsonValue newValue) { + if (jsonValue instanceof JsonObject) { + JsonObject jsonObject = (JsonObject) jsonValue; + JsonObjectBuilder objectBuilder = Json.createObjectBuilder(); + + if (jsonObject.isEmpty()) { + objectBuilder.add(lastReferenceToken, newValue); + } else { + for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) { + objectBuilder.add(entry.getKey(), add(entry.getValue(), currentPosition + 1, referencePosition, newValue)); + if (currentPosition == referencePosition) { + objectBuilder.add(lastReferenceToken, newValue); + } + } + } + return objectBuilder.build(); + } else if (jsonValue instanceof JsonArray) { + JsonArray jsonArray = (JsonArray) jsonValue; + JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + + int arrayIndex = -1; + if (currentPosition == referencePosition) { + arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, true); + } + + int jsonArraySize = jsonArray.size(); + for (int i = 0; i <= jsonArraySize; i++) { + if (i == arrayIndex) { + arrayBuilder.add(newValue); + } + if (i == jsonArraySize) { + break; + } + arrayBuilder.add(add(jsonArray.get(i), currentPosition + 1, referencePosition, newValue)); + } + return arrayBuilder.build(); + } + return jsonValue; + } + + private JsonValue remove(JsonValue jsonValue, int currentPosition, int referencePosition) { + if (jsonValue instanceof JsonObject) { + JsonObject jsonObject = (JsonObject) jsonValue; + JsonObjectBuilder objectBuilder = Json.createObjectBuilder(); + + for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) { + if (currentPosition == referencePosition + && lastReferenceToken.equals(entry.getKey())) { + continue; + } + objectBuilder.add(entry.getKey(), remove(entry.getValue(), currentPosition + 1, referencePosition)); + } + return objectBuilder.build(); + } else if (jsonValue instanceof JsonArray) { + JsonArray jsonArray = (JsonArray) jsonValue; + JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + + int arrayIndex = -1; + if (currentPosition == referencePosition) { + arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, false); + } + + int jsonArraySize = jsonArray.size(); + for (int i = 0; i < jsonArraySize; i++) { + if (i == arrayIndex) { + continue; + } + arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1, referencePosition)); + } + return arrayBuilder.build(); + } + return jsonValue; + } + + private int getArrayIndex(String referenceToken, JsonArray jsonArray, boolean addOperation) { + if (addOperation && referenceToken.equals("-")) { + return jsonArray.size(); + } + + validateArrayIndex(referenceToken); + + try { + int arrayIndex = Integer.parseInt(referenceToken); + int arraySize = addOperation ? jsonArray.size() + 1 : jsonArray.size(); + validateArraySize(jsonArray, arrayIndex, arraySize); + return arrayIndex; + } catch (NumberFormatException e) { + throw new JsonException("'" + referenceToken + "' is no valid array index", e); + } + } + + private void validateJsonPointer(JsonValue target, int size) throws NullPointerException, JsonException { + if (target == null) { + throw new NullPointerException("target must not be null"); + } + + JsonValue jsonValue = target; + for (int i = 1; i < size; i++) { + jsonValue = getValue(jsonValue, referenceTokens.get(i), i, referenceTokens.size() - 1); + } + } + + private void validateArrayIndex(String referenceToken) throws JsonException { + if (referenceToken.startsWith("+") || referenceToken.startsWith("-")) { + throw new JsonException("An array index must not start with '" + referenceToken.charAt(0) + "'"); + } + if (referenceToken.startsWith("0") && referenceToken.length() > 1) { + throw new JsonException("An array index must not start with a leading '0'"); + } + } + + private void validateArraySize(JsonArray jsonArray, int arrayIndex, int arraySize) throws JsonException { + if (arrayIndex >= arraySize) { + throw new JsonException("'" + jsonArray + "' contains no element for index " + arrayIndex); + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/cc830c64/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java index 7750ba6..9b6c722 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java @@ -21,34 +21,38 @@ package org.apache.johnzon.core; import org.junit.Test; import javax.json.Json; +import javax.json.JsonArray; import javax.json.JsonException; +import javax.json.JsonObject; import javax.json.JsonReader; import javax.json.JsonStructure; import javax.json.JsonValue; import java.util.Collections; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class JsonPointerTest { @Test(expected = NullPointerException.class) - public void testConstructorWithNullShouldThrowNullPointerException() { + public void testConstructorWithJsonPointerNull() { new JsonPointer(null); } @Test(expected = JsonException.class) - public void testConstructorWithInvalidJsonPointerShouldThrowJsonException() { + public void testConstructorWithInvalidJsonPointer() { new JsonPointer("a"); } @Test(expected = NullPointerException.class) - public void testGetValueWithNullShouldThrowNullPointerException() { + public void testGetValueWithTargetNull() { JsonPointer jsonPointer = new JsonPointer(""); jsonPointer.getValue(null); } @Test - public void testGetValueWholeDocument() { + public void testGetValueWithWholeDocument() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer(""); @@ -138,7 +142,7 @@ public class JsonPointerTest { } @Test(expected = JsonException.class) - public void testGetValueElementNotExistentShouldThrowJsonException() { + public void testGetValueWithElementNotExistent() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer("/fool"); @@ -146,7 +150,7 @@ public class JsonPointerTest { } @Test - public void testGetValueWholeJsonArray() { + public void testGetValueWithWholeJsonArray() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer("/foo"); @@ -155,7 +159,7 @@ public class JsonPointerTest { } @Test - public void testGetValueJsonArrayElement() { + public void testGetValueWithJsonArray() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer("/foo/0"); @@ -164,7 +168,7 @@ public class JsonPointerTest { } @Test(expected = JsonException.class) - public void testGetValueJsonArrayElementNotExistentShouldThrowJsonException() { + public void testGetValueWithJsonArrayIndexOutOfRange() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer("/foo/2"); @@ -172,7 +176,7 @@ public class JsonPointerTest { } @Test(expected = JsonException.class) - public void testGetValueJsonArrayElementNoNumberShouldThrowJsonException() { + public void testGetValueWithJsonArrayIndexNoNumber() { JsonStructure jsonDocument = getJsonDocument(); JsonPointer jsonPointer = new JsonPointer("/foo/a"); @@ -180,14 +184,407 @@ public class JsonPointerTest { } @Test(expected = JsonException.class) - public void testGetValueJsonArrayElementLeadingZeroShouldThrowJsonException() { + public void testGetValueWithJsonArrayLeadingZeroIndex() { JsonStructure jsonDocument = getJsonDocument(); - JsonPointer jsonPointer = new JsonPointer("/foo/001"); + JsonPointer jsonPointer = new JsonPointer("/foo/01"); JsonValue result = jsonPointer.getValue(jsonDocument); assertEquals("\"bar\"", result.toString()); } + @Test(expected = JsonException.class) + public void testGetValueWithJsonArrayInvalidIndex() { + JsonStructure jsonDocument = getJsonDocument(); + + JsonPointer jsonPointer = new JsonPointer("/foo/-1"); + jsonPointer.getValue(jsonDocument); + } + + @Test(expected = NullPointerException.class) + public void testAddJsonStructureWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer(""); + jsonPointer.add((JsonStructure) null, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testAddJsonStructureWithTypeValueNotTypeTarget() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonObject target = Json.createObjectBuilder().build(); + JsonArray value = Json.createArrayBuilder().build(); + + jsonPointer.add((JsonStructure) target, value); + } + + @Test + public void testAddJsonStructureWithEmptyJsonPointer() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonStructure target = Json.createObjectBuilder().build(); + JsonObject value = Json.createObjectBuilder() + .add("foo", "bar").build(); // { "foo": "bar" } + + JsonStructure result = jsonPointer.add(target, value); + assertEquals("{\"foo\":\"bar\"}", result.toString()); + } + + @Test(expected = NullPointerException.class) + public void testAddJsonObjectWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer(""); + jsonPointer.add((JsonObject) null, new JsonStringImpl("qux")); + } + + @Test(expected = NullPointerException.class) + public void testAddJsonArrayWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer(""); + jsonPointer.add((JsonArray) null, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testAddArrayElementWithInvalidIndex() { + JsonPointer jsonPointer = new JsonPointer("/+"); + JsonStructure target = Json.createArrayBuilder().build(); + + jsonPointer.add(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testAddArrayElementWithIndexOutOfRange() { + JsonPointer jsonPointer = new JsonPointer("/1"); + JsonStructure target = Json.createArrayBuilder().build(); + + jsonPointer.add(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testAddArrayElementWithLeadingZeroIndex() { + JsonPointer jsonPointer = new JsonPointer("/01"); + JsonStructure target = Json.createArrayBuilder() + .add("foo").build(); + + jsonPointer.add(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testAddArrayElementWithIndexNoNumber() { + JsonPointer jsonPointer = new JsonPointer("/a"); + JsonStructure target = Json.createArrayBuilder() + .add("foo").build(); + + jsonPointer.add(target, new JsonStringImpl("qux")); + } + + @Test + public void testAddObject() { + JsonPointer jsonPointer = new JsonPointer("/child"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar").build(); // {"foo":"bar"} + JsonObject value = Json.createObjectBuilder() + .add("grandchild", Json.createObjectBuilder()).build(); // {"grandchild":{}} + + JsonStructure result = jsonPointer.add(target, value); + assertEquals("{\"foo\":\"bar\",\"child\":{\"grandchild\":{}}}", result.toString()); // {"foo":"bar","child":{"grandchild":{}}} + } + + @Test + public void testAddObjectMember() { + JsonPointer jsonPointer = new JsonPointer("/baz"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar").build(); // {"foo":"bar"} + + JsonStructure result = jsonPointer.add(target, new JsonStringImpl("qux")); + assertEquals("{\"foo\":\"bar\",\"baz\":\"qux\"}", result.toString()); // {"foo":"bar","baz":"qux"} + } + + @Test + public void testAddFirstObjectMember() { + JsonPointer jsonPointer = new JsonPointer("/foo"); + JsonStructure target = Json.createObjectBuilder().build(); // {} + + JsonStructure result = jsonPointer.add(target, new JsonStringImpl("bar")); + assertEquals("{\"foo\":\"bar\"}", result.toString()); // {"foo":"bar"} + } + + @Test(expected = JsonException.class) + public void testAddObjectMemberWithNonexistentTarget() { + JsonPointer jsonPointer = new JsonPointer("/baz/bat"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar").build(); // {"foo":"bar"} + + jsonPointer.add(target, new JsonStringImpl("qux")); + } + + @Test + public void testAddReplaceObjectMember() { + JsonPointer jsonPointer = new JsonPointer("/baz"); + JsonStructure target = Json.createObjectBuilder() + .add("baz", "qux") + .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"} + + JsonStructure result = jsonPointer.add(target, new JsonStringImpl("boo")); + assertEquals("{\"baz\":\"boo\",\"foo\":\"bar\"}", result.toString()); // {"baz":"boo","foo":"bar"} + } + + @Test + public void testAddArray() { + JsonPointer jsonPointer = new JsonPointer("/0/-"); + JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar")).build(); // [["bar"]] + JsonArray value = Json.createArrayBuilder() + .add("abc") + .add("def").build();// ["abc","def"] + + JsonStructure result = jsonPointer.add(target, value); + assertEquals("[[\"bar\",[\"abc\",\"def\"]]]", result.toString()); // [["bar",["abc","def"]]] + } + + @Test + public void testAddArrayElement() { + JsonPointer jsonPointer = new JsonPointer("/foo/1"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add("bar") + .add("baz")).build(); // {"foo":["bar","baz"]} + + JsonStructure result = jsonPointer.add(target, new JsonStringImpl("qux")); + assertEquals("{\"foo\":[\"bar\",\"qux\",\"baz\"]}", result.toString()); // {"foo":["bar","qux","baz"]} + } + + @Test(expected = NullPointerException.class) + public void testRemoveJsonObjectWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer("/"); + jsonPointer.remove((JsonObject) null); + } + + @Test(expected = JsonException.class) + public void testRemoveJsonObjectWithEmptyJsonPointer() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonObject target = Json.createObjectBuilder().build(); + + jsonPointer.remove(target); + } + + @Test(expected = NullPointerException.class) + public void testRemoveJsonArrayWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer("/"); + jsonPointer.remove((JsonArray) null); + } + + @Test(expected = JsonException.class) + public void testRemoveJsonArrayWithEmptyJsonPointer() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonArray target = Json.createArrayBuilder().build(); + + jsonPointer.remove(target); + } + + @Test(expected = JsonException.class) + public void testRemoveArrayElementWithIndexNoNumber() { + JsonPointer jsonPointer = new JsonPointer("/foo/a"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // {"foo":["bar","qux","baz"]} + + jsonPointer.remove(target); + } + + @Test(expected = JsonException.class) + public void testRemoveArrayElementWithIndexOutOfRange() { + JsonPointer jsonPointer = new JsonPointer("/foo/3"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // {"foo":["bar","qux","baz"]} + + jsonPointer.remove(target); + } + + @Test(expected = JsonException.class) + public void testRemoveArrayElementWithInvalidIndex() { + JsonPointer jsonPointer = new JsonPointer("/foo/+"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // {"foo":["bar","qux","baz"]} + + jsonPointer.remove(target); + } + + @Test(expected = JsonException.class) + public void testRemoveArrayElementWithLeadingZeroIndex() { + JsonPointer jsonPointer = new JsonPointer("/foo/01"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // {"foo":["bar","qux","baz"]} + + jsonPointer.remove(target); + } + + @Test + public void testRemoveArrayElement() { + JsonPointer jsonPointer = new JsonPointer("/0/1"); + JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + JsonStructure result = jsonPointer.remove(target); + assertEquals("[[\"bar\",\"baz\"]]", result.toString()); // [["bar","baz"]] + } + + @Test + public void testRemoveObjectMember() { + JsonPointer jsonPointer = new JsonPointer("/baz"); + JsonStructure target = Json.createObjectBuilder() + .add("baz", "qux") + .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"} + + JsonStructure result = jsonPointer.remove(target); + assertEquals("{\"foo\":\"bar\"}", result.toString()); // {"foo":"bar"} + } + + @Test(expected = NullPointerException.class) + public void testReplaceJsonObjectWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer("/"); + jsonPointer.replace((JsonObject) null, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testReplaceJsonObjectWithEmptyJsonPointer() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonObject target = Json.createObjectBuilder().build(); + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test(expected = NullPointerException.class) + public void testReplaceJsonArrayWithTargetNull() { + JsonPointer jsonPointer = new JsonPointer("/"); + jsonPointer.replace((JsonArray) null, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testReplaceJsonArrayWithEmptyJsonPointer() { + JsonPointer jsonPointer = new JsonPointer(""); + JsonArray target = Json.createArrayBuilder().build(); + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test + public void testReplaceArrayElement() { + JsonPointer jsonPointer = new JsonPointer("/1/1"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add(Json.createArrayBuilder() + .add("abc") + .add("def")).build(); // ["bar",["abc","def"]] + + JsonStructure result = jsonPointer.replace(target, new JsonStringImpl("qux")); + assertEquals("[\"bar\",[\"abc\",\"qux\"]]", result.toString()); // ["bar",["abc","qux"]] + } + + @Test(expected = JsonException.class) + public void testReplaceArrayElementWithIndexOutOfRange() { + JsonPointer jsonPointer = new JsonPointer("/1/2"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add(Json.createArrayBuilder() + .add("abc") + .add("def")).build(); // ["bar",["abc","def"]] + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testReplaceArrayElementWithIndexNoNumber() { + JsonPointer jsonPointer = new JsonPointer("/1/a"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add(Json.createArrayBuilder() + .add("abc") + .add("def")).build(); // ["bar",["abc","def"]] + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testReplaceArrayElementWithLeadingZeroIndex() { + JsonPointer jsonPointer = new JsonPointer("/1/01"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add(Json.createArrayBuilder() + .add("abc") + .add("def")).build(); // ["bar",["abc","def"]] + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test(expected = JsonException.class) + public void testReplaceArrayElementWithInvalidIndex() { + JsonPointer jsonPointer = new JsonPointer("/1/+"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add(Json.createArrayBuilder() + .add("abc") + .add("def")).build(); // ["bar",["abc","def"]] + + jsonPointer.replace(target, new JsonStringImpl("qux")); + } + + @Test + public void testReplaceObjectMember() { + JsonPointer jsonPointer = new JsonPointer("/baz"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar") + .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"} + + JsonStructure result = jsonPointer.replace(target, new JsonStringImpl("boo")); + assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); // {"foo":"bar","baz":"boo"} + } + + @Test(expected = JsonException.class) + public void testReplaceObjectMemberWithNonexistentTarget1() { + JsonPointer jsonPointer = new JsonPointer("/baz/a"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar") + .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"} + + JsonStructure result = jsonPointer.replace(target, new JsonStringImpl("boo")); + assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); // {"foo":"bar","baz":"boo"} + } + + @Test(expected = JsonException.class) + public void testReplaceObjectMemberWithNonexistentTarget2() { + JsonPointer jsonPointer = new JsonPointer("/fo"); + JsonStructure target = Json.createObjectBuilder() + .add("foo", "bar") + .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"} + + JsonStructure result = jsonPointer.replace(target, new JsonStringImpl("boo")); + assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); // {"foo":"bar","baz":"boo"} + } + + @Test + public void testEqualsTrue() { + JsonPointer jsonPointer1 = new JsonPointer("/foo/1"); + JsonPointer jsonPointer2 = new JsonPointer("/foo/1"); + assertTrue(jsonPointer1.equals(jsonPointer2)); + } + + @Test + public void testEqualsFalse() { + JsonPointer jsonPointer1 = new JsonPointer("/foo/1"); + JsonPointer jsonPointer2 = new JsonPointer("/foo/2"); + assertFalse(jsonPointer1.equals(jsonPointer2)); + } + private JsonStructure getJsonDocument() { JsonReader reader = Json.createReaderFactory(Collections.<String, Object>emptyMap()).createReader( Thread.currentThread().getContextClassLoader().getResourceAsStream("json/jsonPointerTest.json"));
