This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch rmannibucau/jsonpointer-compliance-proposal in repository https://gitbox.apache.org/repos/asf/johnzon.git
commit 437dad68a726883a7ca4588690478f7fd3301d30 Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Wed Dec 2 13:09:28 2020 +0100 [JOHNZON-325] jsonp-strict module --- .../johnzon/core/DefaultJsonPointerFactory.java | 31 +++++ .../org/apache/johnzon/core/JsonPatchImpl.java | 39 ++---- .../org/apache/johnzon/core/JsonPointerImpl.java | 2 +- .../org/apache/johnzon/core/JsonProviderImpl.java | 15 +- .../johnzon/core/spi/JsonPointerFactory.java | 30 ++++ .../org/apache/johnzon/core/JsonPointerTest.java | 113 +-------------- johnzon-jsonp-strict/pom.xml | 81 +++++++++++ .../jsonp/strict/StrictJsonPointerFactory.java | 42 ++++++ .../org.apache.johnzon.core.spi.JsonPointerFactory | 1 + .../jsonp/strict/StrictJsonPointerFactoryTest.java | 153 +++++++++++++++++++++ pom.xml | 4 +- src/site/markdown/index.md | 16 +++ 12 files changed, 386 insertions(+), 141 deletions(-) diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/DefaultJsonPointerFactory.java b/johnzon-core/src/main/java/org/apache/johnzon/core/DefaultJsonPointerFactory.java new file mode 100644 index 0000000..152f029 --- /dev/null +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/DefaultJsonPointerFactory.java @@ -0,0 +1,31 @@ +/* + * 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 org.apache.johnzon.core.spi.JsonPointerFactory; + +import javax.json.JsonPointer; +import javax.json.spi.JsonProvider; + +public class DefaultJsonPointerFactory implements JsonPointerFactory { + @Override + public JsonPointer createPointer(final JsonProvider provider, final String path) { + return new JsonPointerImpl(provider, path); + } +} 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 390c438..41ceedf 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 @@ -29,6 +29,7 @@ import javax.json.JsonException; import javax.json.JsonObject; import javax.json.JsonObjectBuilder; import javax.json.JsonPatch; +import javax.json.JsonPointer; import javax.json.JsonStructure; import javax.json.JsonValue; import javax.json.spi.JsonProvider; @@ -147,9 +148,11 @@ class JsonPatchImpl implements JsonPatch { static class PatchValue { private final JsonProvider provider; private final JsonPatch.Operation operation; - private final JsonPointerImpl path; - private final JsonPointerImpl from; + private final JsonPointer path; + private final JsonPointer from; private final JsonValue value; + private final String pathPtr; + private final String fromPtr; private volatile String str; private volatile JsonObject json; @@ -162,11 +165,13 @@ class JsonPatchImpl implements JsonPatch { final JsonValue value) { this.provider = provider; this.operation = operation; - this.path = new JsonPatchPointerImpl(provider, path); + this.path = provider.createPointer(path); + this.pathPtr = path; + this.fromPtr = from; // ignore from if we do not need it if (operation == JsonPatch.Operation.MOVE || operation == JsonPatch.Operation.COPY) { - this.from = new JsonPatchPointerImpl(provider, from); + this.from = provider.createPointer(from); } else { this.from = null; } @@ -233,10 +238,10 @@ class JsonPatchImpl implements JsonPatch { if (json == null) { JsonObjectBuilder builder = provider.createObjectBuilder() .add("op", operation.name().toLowerCase()) - .add("path", path.getJsonPointer()); + .add("path", pathPtr); - if (from != null) { - builder.add("from", from.getJsonPointer()); + if (fromPtr != null) { + builder.add("from", fromPtr); } if (value != null) { @@ -250,24 +255,4 @@ class JsonPatchImpl implements JsonPatch { return json; } } - - public static class JsonPatchPointerImpl extends JsonPointerImpl { - - /** - * Constructs and initializes a JsonPointer. - * - * @param provider the JsonProvider - * @param jsonPointer the JSON Pointer string - * @throws NullPointerException if {@code jsonPointer} is {@code null} - * @throws JsonException if {@code jsonPointer} is not a valid JSON Pointer - */ - public JsonPatchPointerImpl(final JsonProvider provider, final String jsonPointer) { - super(provider, jsonPointer); - } - - @Override - protected int minusShift() { - return 1; - } - } } 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 2f1a76d..036986e 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 @@ -499,7 +499,7 @@ public class JsonPointerImpl implements JsonPointer { * @return the shift to apply on minus. For pointer, it's 0 because we need the element right after the last. */ protected int minusShift() { - return 0; + return 1; } private void validateJsonPointer(JsonValue target, int size) throws NullPointerException, JsonException { 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 282f286..c3147d9 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 @@ -18,6 +18,8 @@ */ package org.apache.johnzon.core; +import org.apache.johnzon.core.spi.JsonPointerFactory; + import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; @@ -27,7 +29,9 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; import java.util.Map; +import java.util.ServiceLoader; import java.util.function.Supplier; +import java.util.stream.StreamSupport; import javax.json.JsonArray; import javax.json.JsonArrayBuilder; @@ -52,6 +56,8 @@ import javax.json.stream.JsonGeneratorFactory; import javax.json.stream.JsonParser; import javax.json.stream.JsonParserFactory; +import static java.util.Comparator.comparing; + public class JsonProviderImpl extends JsonProvider implements Serializable { private final Supplier<BufferStrategy.BufferProvider<char[]>> bufferProvider = new Cached<>(() -> BufferStrategyFactory.valueOf(System.getProperty(AbstractJsonFactory.BUFFER_STRATEGY, "QUEUE")) @@ -63,6 +69,13 @@ public class JsonProviderImpl extends JsonProvider implements Serializable { private final JsonWriterFactory writerFactory = new JsonWriterFactoryImpl(null); private final Supplier<JsonBuilderFactory> builderFactory = new Cached<>(() -> new JsonBuilderFactoryImpl(null, bufferProvider.get())); + private final JsonPointerFactory jsonPointerFactory; + + public JsonProviderImpl() { + jsonPointerFactory = StreamSupport.stream(ServiceLoader.load(JsonPointerFactory.class).spliterator(), false) + .min(comparing(JsonPointerFactory::ordinal)) + .orElseGet(DefaultJsonPointerFactory::new); + } @Override public JsonParser createParser(final InputStream in) { @@ -203,7 +216,7 @@ public class JsonProviderImpl extends JsonProvider implements Serializable { @Override public JsonPointer createPointer(String path) { - return new JsonPointerImpl(this, path); + return jsonPointerFactory.createPointer(this, path); } @Override diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/spi/JsonPointerFactory.java b/johnzon-core/src/main/java/org/apache/johnzon/core/spi/JsonPointerFactory.java new file mode 100644 index 0000000..1b0a51a --- /dev/null +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/spi/JsonPointerFactory.java @@ -0,0 +1,30 @@ +/* + * 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.spi; + +import javax.json.JsonPointer; +import javax.json.spi.JsonProvider; + +public interface JsonPointerFactory { + JsonPointer createPointer(JsonProvider provider, String path); + + default int ordinal() { + return 0; + } +} 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 f9e782c..8389f41 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 @@ -455,21 +455,8 @@ public class JsonPointerTest { assertEquals("[[\"bar\",\"baz\"]]", result.toString()); // [["bar","baz"]] } - @Test(expected = JsonException.class) - public void testRemoveLastArrayElement() { - JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/0/-"); - JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - - JsonStructure result = jsonPointer.remove(target); - assertEquals("[[\"bar\",\"qux\"]]", result.toString()); // [["bar","qux"]] - } - public void testRemoveLastArrayElementWithPatch() { - JsonPointerImpl jsonPointer = new JsonPatchImpl.JsonPatchPointerImpl(JsonProvider.provider(), "/0/-"); + JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/0/-"); JsonStructure target = Json.createArrayBuilder() .add(Json.createArrayBuilder() .add("bar") @@ -480,78 +467,6 @@ public class JsonPointerTest { assertEquals("[[\"bar\",\"qux\"]]", result.toString()); // [["bar","qux"]] } - @Test(expected = JsonException.class) - public void testGetLastArrayElementSimple() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); - final JsonStructure target = Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz") - .build(); - - jsonPointer.getValue(target); - } - - @Test(expected = JsonException.class) - public void testGetLastArrayElement() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); - final JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - - jsonPointer.getValue(target); - } - - @Test(expected = JsonException.class) - public void testGetLastArrayElement2() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/0/-"); - final JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - - jsonPointer.getValue(target); - } - - @Test(expected = JsonException.class) - public void testReplaceLastArrayElementSimple() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); - final JsonStructure target = Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz") - .build(); - - jsonPointer.replace(target, new JsonStringImpl("won't work")); - } - - @Test(expected = JsonException.class) - public void testReplaceLastArrayElement() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); - final JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - - jsonPointer.replace(target, new JsonStringImpl("won't work")); - } - - @Test(expected = JsonException.class) - public void testReplaceLastArrayElement2() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/0/-"); - final JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - - jsonPointer.replace(target, new JsonStringImpl("won't work")); - } - @Test public void testAddLastArrayElementSimple() { final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); @@ -591,22 +506,9 @@ public class JsonPointerTest { assertEquals("[[\"bar\",\"qux\",\"baz\",\"xyz\"]]", result.toString()); } - @Test(expected = JsonException.class) - public void testRemoveLastArrayElementSimple() { - JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); - JsonStructure target = Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz") - .build(); - - JsonStructure result = jsonPointer.remove(target); - assertEquals("[\"bar\",\"qux\"]", result.toString()); - } - @Test public void testRemoveLastArrayElementSimpleWithPatch() { - JsonPointerImpl jsonPointer = new JsonPatchImpl.JsonPatchPointerImpl(JsonProvider.provider(), "/-"); + JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); JsonStructure target = Json.createArrayBuilder() .add("bar") .add("qux") @@ -624,17 +526,6 @@ public class JsonPointerTest { jsonPointer.remove(target); } - @Test(expected = JsonException.class) - public void testRemoveLastArrayElementFromEmpty() { - final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/0/-"); - final JsonStructure target = Json.createArrayBuilder() - .add(Json.createArrayBuilder() - .add("bar") - .add("qux") - .add("baz")).build(); // [["bar","qux","baz"]] - jsonPointer.remove(target); - } - @Test public void testRemoveObjectMember() { JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/baz"); diff --git a/johnzon-jsonp-strict/pom.xml b/johnzon-jsonp-strict/pom.xml new file mode 100644 index 0000000..04a9ee7 --- /dev/null +++ b/johnzon-jsonp-strict/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>johnzon</artifactId> + <groupId>org.apache.johnzon</groupId> + <version>1.2.9-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>johnzon-jsonp-strict</artifactId> + <name>Johnzon :: JSON-P Strict JSON Pointer Implementation (spec compliant)</name> + <packaging>bundle</packaging> + + <properties> + <staging.directory>${project.parent.reporting.outputDirectory}</staging.directory> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.johnzon</groupId> + <artifactId>johnzon-core</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.2.2</version> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Import-Package> + * + </Import-Package> + <Require-Capability> + osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)" + </Require-Capability> + <_contract> + !JavaAnnotation, + !JavaCDI, + !JavaJAXRS, + JavaJSONP + </_contract> + <Provide-Capability>osgi.serviceloader;osgi.serviceloader=org.apache.johnzon.core.spi.JsonPointerFactory</Provide-Capability> + </instructions> + </configuration> + <dependencies> + <dependency> + <groupId>biz.aQute.bnd</groupId> + <artifactId>biz.aQute.bndlib</artifactId> + <version>4.3.1</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> +</project> diff --git a/johnzon-jsonp-strict/src/main/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactory.java b/johnzon-jsonp-strict/src/main/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactory.java new file mode 100644 index 0000000..915aeb2 --- /dev/null +++ b/johnzon-jsonp-strict/src/main/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactory.java @@ -0,0 +1,42 @@ +/* + * 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.jsonp.strict; + +import org.apache.johnzon.core.JsonPointerImpl; +import org.apache.johnzon.core.spi.JsonPointerFactory; + +import javax.json.JsonPointer; +import javax.json.spi.JsonProvider; + +public class StrictJsonPointerFactory implements JsonPointerFactory { + @Override + public JsonPointer createPointer(final JsonProvider provider, final String path) { + return new StrictJsonPointerImpl(provider, path); + } + + private static class StrictJsonPointerImpl extends JsonPointerImpl { + public StrictJsonPointerImpl(final JsonProvider provider, final String path) { + super(provider, path); + } + + protected int minusShift() { + return 0; + } + } +} diff --git a/johnzon-jsonp-strict/src/main/resources/META-INF/services/org.apache.johnzon.core.spi.JsonPointerFactory b/johnzon-jsonp-strict/src/main/resources/META-INF/services/org.apache.johnzon.core.spi.JsonPointerFactory new file mode 100644 index 0000000..088626a --- /dev/null +++ b/johnzon-jsonp-strict/src/main/resources/META-INF/services/org.apache.johnzon.core.spi.JsonPointerFactory @@ -0,0 +1 @@ +org.apache.johnzon.jsonp.strict.StrictJsonPointerFactory diff --git a/johnzon-jsonp-strict/src/test/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactoryTest.java b/johnzon-jsonp-strict/src/test/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactoryTest.java new file mode 100644 index 0000000..bd6e0ec --- /dev/null +++ b/johnzon-jsonp-strict/src/test/java/org/apache/johnzon/jsonp/strict/StrictJsonPointerFactoryTest.java @@ -0,0 +1,153 @@ +/* + * 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.jsonp.strict; + +import org.apache.johnzon.core.JsonPointerImpl; +import org.junit.Test; + +import javax.json.Json; +import javax.json.JsonException; +import javax.json.JsonPointer; +import javax.json.JsonStructure; +import javax.json.spi.JsonProvider; + +import static org.junit.Assert.assertEquals; + +public class StrictJsonPointerFactoryTest { + @Test + public void validMinusUsage() { + final JsonPointerImpl jsonPointer = new JsonPointerImpl(JsonProvider.provider(), "/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + final JsonStructure result = jsonPointer.add(target, Json.createValue("xyz")); + assertEquals("[[\"bar\",\"qux\",\"baz\"],\"xyz\"]", result.toString()); + } + + @Test(expected = JsonException.class) + public void testReplaceLastArrayElement2() { + final JsonPointer jsonPointer = Json.createPointer("/0/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + jsonPointer.replace(target, Json.createValue("won't work")); + } + + @Test(expected = JsonException.class) + public void testRemoveLastArrayElement() { + JsonPointer jsonPointer = Json.createPointer("/0/-"); + JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + JsonStructure result = jsonPointer.remove(target); + assertEquals("[[\"bar\",\"qux\"]]", result.toString()); // [["bar","qux"]] + } + + @Test(expected = JsonException.class) + public void testReplaceLastArrayElement() { + final JsonPointer jsonPointer = Json.createPointer("/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + jsonPointer.replace(target, Json.createValue("won't work")); + } + + @Test(expected = JsonException.class) + public void testGetLastArrayElementSimple() { + final JsonPointer jsonPointer = Json.createPointer("/-"); + final JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz") + .build(); + + jsonPointer.getValue(target); + } + + @Test(expected = JsonException.class) + public void testGetLastArrayElement2() { + final JsonPointer jsonPointer = Json.createPointer("/0/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + jsonPointer.getValue(target); + } + + @Test(expected = JsonException.class) + public void testRemoveLastArrayElementFromEmpty() { + final JsonPointer jsonPointer = Json.createPointer("/0/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + jsonPointer.remove(target); + } + + @Test(expected = JsonException.class) + public void testRemoveLastArrayElementSimple() { + JsonPointer jsonPointer = Json.createPointer("/-"); + JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz") + .build(); + + JsonStructure result = jsonPointer.remove(target); + assertEquals("[\"bar\",\"qux\"]", result.toString()); + } + + @Test(expected = JsonException.class) + public void testGetLastArrayElement() { + final JsonPointer jsonPointer = Json.createPointer("/-"); + final JsonStructure target = Json.createArrayBuilder() + .add(Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz")).build(); // [["bar","qux","baz"]] + + jsonPointer.getValue(target); + } + + @Test(expected = JsonException.class) + public void testReplaceLastArrayElementSimple() { + final JsonPointer jsonPointer = Json.createPointer("/-"); + final JsonStructure target = Json.createArrayBuilder() + .add("bar") + .add("qux") + .add("baz") + .build(); + + jsonPointer.replace(target, Json.createValue("won't work")); + } +} diff --git a/pom.xml b/pom.xml index d64f601..7cd7ce6 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,7 @@ <module>johnzon-jsonschema</module> <module>johnzon-osgi</module> <module>johnzon-jsonlogic</module> + <module>johnzon-jsonp-strict</module> </modules> <dependencyManagement> @@ -150,6 +151,7 @@ <groupId>org.apache.rat</groupId> <artifactId>apache-rat-plugin</artifactId> <configuration> + <consoleOutput>true</consoleOutput> <includes> <include>src/**/*</include> <include>pom.xml</include> @@ -162,7 +164,7 @@ <exclude>*.iws</exclude> <exclude>*.iml</exclude> <exclude>*.ipr</exclude> - <exclude>**/META-INF/services/javax.*</exclude> + <exclude>**/META-INF/services/*</exclude> <exclude>**/*.json</exclude> <exclude>**/*.yml</exclude> <exclude>**/bench/*.txt</exclude> diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 3ee6c0e..52cead3 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -52,6 +52,22 @@ You'll surely want to add the API as dependency too: </dependency> ]]></pre> +### JSON-P Strict Compliance (stable) + +<pre class="prettyprint linenums"><![CDATA[ +<dependency> + <groupId>org.apache.johnzon</groupId> + <artifactId>johnzon-jsonp-strict</artifactId> + <version>${johnzon.version}</version> +</dependency> +]]></pre> + +This module enables to enforce a strict compliance of JsonPointer behavior on `/-` usage. +Johnzon default implementation enables to use it as "remove last element" when using a remove patch (or not add semantic). +This module enforces this case to be invalid to be closer to the intended wording of the JSON Pointer underlying specs. + +Note that you can even customize this behavior implementing your own `JsonPointerFactory` and changing the ordinal value to take a highest priority. + ### Mapper (stable) <pre class="prettyprint linenums"><![CDATA[