From 2c60b44a5fc0565a97ef56d19e7461a75cb36790 Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Sun, 14 Aug 2022 00:44:44 -0300 Subject: [PATCH] Add support to Jackson's JsonNode --- jsonmerge-core/pom.xml | 8 + .../provider/JacksonJsonNodeJsonProvider.java | 168 ++++++++++++++++++ ...MergerJacksonJsonNodeJsonProviderTest.java | 108 +++++++++++ .../JacksonJsonNodeJsonProviderTest.java | 42 +++++ pom.xml | 1 - 5 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 jsonmerge-core/src/main/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProvider.java create mode 100644 jsonmerge-core/src/test/java/net/obvj/jsonmerge/JsonMergerJacksonJsonNodeJsonProviderTest.java create mode 100644 jsonmerge-core/src/test/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProviderTest.java diff --git a/jsonmerge-core/pom.xml b/jsonmerge-core/pom.xml index 8bea437..07fa7f8 100644 --- a/jsonmerge-core/pom.xml +++ b/jsonmerge-core/pom.xml @@ -35,6 +35,7 @@ 2.7.0 20220320 2.9.1 + 2.13.3 @@ -73,5 +74,12 @@ true + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + true + + diff --git a/jsonmerge-core/src/main/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProvider.java b/jsonmerge-core/src/main/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProvider.java new file mode 100644 index 0000000..2bfacf2 --- /dev/null +++ b/jsonmerge-core/src/main/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProvider.java @@ -0,0 +1,168 @@ +/* + * Copyright 2022 obvj.net + * + * Licensed 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 net.obvj.jsonmerge.provider; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * A specialized {@link JsonProvider} implementation for {@code Jackson}'s + * {@link JsonNode}. + * + * @author oswaldo.bapvic.jr (Oswaldo Junior) + * @since 1.0.0 + * + * @see Jackson Project home + * @see JsonNode + * @see ObjectNode + * @see ArrayNode + */ +public class JacksonJsonNodeJsonProvider implements JsonProvider +{ + private ObjectNode toJsonObject(final Object jsonObject) + { + return (ObjectNode) jsonObject; + } + + private ArrayNode toJsonArray(final Object jsonArray) + { + return (ArrayNode) jsonArray; + } + + /** + * Converts an object to a {@link JsonNode}. + * + * @param object the object to be converted + * @return a {@link JsonNode} from the specified object + */ + public JsonNode toJsonNode(final Object object) + { + return object instanceof JsonNode ? (JsonNode) object + : new ObjectMapper().convertValue(object, JsonNode.class); + } + + @Override + public boolean isJsonObject(final Object object) + { + return object instanceof ObjectNode; + } + + @Override + public boolean isJsonArray(final Object object) + { + return object instanceof ArrayNode; + } + + @Override + public boolean isEmpty(final Object jsonObject) + { + return toJsonObject(jsonObject).isEmpty(); + } + + @Override + public Object newJsonObject() + { + return JsonNodeFactory.instance.objectNode(); + } + + @Override + public Object newJsonObject(final Object sourceJsonObject) + { + return JsonNodeFactory.instance.objectNode().setAll(toJsonObject(sourceJsonObject)); + } + + @Override + public Object newJsonArray() + { + return JsonNodeFactory.instance.arrayNode(); + } + + @Override + public Object newJsonArray(final Object sourceJsonArray) + { + return JsonNodeFactory.instance.arrayNode().addAll(toJsonArray(sourceJsonArray)); + } + + @Override + public Set> entrySet(final Object jsonObject) + { + Iterator> iterator = toJsonObject(jsonObject).fields(); + Iterable> iterable = () -> iterator; + return (Set) StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toSet()); + } + + @Override + public Object get(final Object jsonObject, final String key) + { + return toJsonObject(jsonObject).get(key); + } + + + @Override + public void put(final Object jsonObject, final String key, final Object value) + { + toJsonObject(jsonObject).set(key, toJsonNode(value)); + } + + @Override + public void putIfAbsent(final Object jsonObject, final String key, final Object value) + { + ObjectNode json = toJsonObject(jsonObject); + if (json.get(key) == null) + { + json.set(key, toJsonNode(value)); + } + } + + @Override + public void add(final Object jsonArray, final Object element) + { + toJsonArray(jsonArray).add(toJsonNode(element)); + } + + @Override + public void forEachElementInArray(final Object jsonArray, final Consumer action) + { + toJsonArray(jsonArray).forEach(action); + } + + @Override + public boolean arrayContains(final Object jsonArray, final Object element) + { + return stream(jsonArray).anyMatch(element::equals); + } + + @Override + public Stream stream(final Object jsonArray) + { + Spliterator spliterator = toJsonArray(jsonArray).spliterator(); + return (Stream) StreamSupport.stream(spliterator, false); + } + +} diff --git a/jsonmerge-core/src/test/java/net/obvj/jsonmerge/JsonMergerJacksonJsonNodeJsonProviderTest.java b/jsonmerge-core/src/test/java/net/obvj/jsonmerge/JsonMergerJacksonJsonNodeJsonProviderTest.java new file mode 100644 index 0000000..5601c1a --- /dev/null +++ b/jsonmerge-core/src/test/java/net/obvj/jsonmerge/JsonMergerJacksonJsonNodeJsonProviderTest.java @@ -0,0 +1,108 @@ +package net.obvj.jsonmerge; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URL; +import java.util.List; + +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.ParseContext; +import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; + +import net.obvj.jsonmerge.provider.JacksonJsonNodeJsonProvider; + +/** + * Unit tests for the {@link JsonMerger} using the {@link JacksonJsonNodeJsonProvider}. + * + * @author oswaldo.bapvic.jr + * @since 1.0.0 + */ +class JsonMergerJacksonJsonNodeJsonProviderTest extends JsonMergerTest +{ + + private static Configuration configuration = Configuration.builder() + .jsonProvider(new com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider()) + .mappingProvider(new JacksonMappingProvider()).build(); + + private static ParseContext context = JsonPath.using(configuration); + + @Override + JacksonJsonNodeJsonProvider getProvider() + { + return new JacksonJsonNodeJsonProvider(); + } + + @Override + ObjectNode fromString(String string) + { + try + { + return new JsonMapper().readValue(string, ObjectNode.class); + } + catch (Exception e) + { + throw new AssertionError("Unable to parse JSON string", e); + } + } + + @Override + ObjectNode fromFile(String path) + { + try + { + URL resource = JsonMerger.class.getClassLoader().getResource(path); + return new JsonMapper().readValue(resource.openStream(), ObjectNode.class); + } + catch (Exception e) + { + throw new AssertionError("Unable to load JSON file", e); + } + } + + @Override + Object get(ObjectNode object, String jsonPath) + { + return context.parse(object).read(jsonPath); + } + + @Override + void assertElement(Object expected, Object actual) + { + assertEquals(getProvider().toJsonNode(expected), actual); + } + + @Override + void assertArray(List expected, ObjectNode result, String jsonPath) + { + assertArray(expected, result, jsonPath, true); + } + + @Override + void assertArray(List expected, ObjectNode result, String jsonPath, boolean exactSize) + { + ArrayNode array = (ArrayNode) get(result, jsonPath); + assertArray(expected, array, exactSize); + } + + private void assertArray(List expected, ArrayNode array, boolean exactSize) + { + if (exactSize) + { + assertEquals(expected.size(), array.size()); + } + + expected.forEach(expectedElement -> + { + assertTrue( + getProvider().stream(array) + .anyMatch(getProvider().toJsonNode(expectedElement)::equals), + () -> String.format("Expected element %s not found", expectedElement)); + }); + } + +} diff --git a/jsonmerge-core/src/test/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProviderTest.java b/jsonmerge-core/src/test/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProviderTest.java new file mode 100644 index 0000000..b630eb2 --- /dev/null +++ b/jsonmerge-core/src/test/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProviderTest.java @@ -0,0 +1,42 @@ +package net.obvj.jsonmerge.provider; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; + +/** + * Unit tests for the {@link JacksonJsonNodeJsonProvider} class. + * + * @author oswaldo.bapvic.jr + * @since 1.1.0 + */ +class JacksonJsonNodeJsonProviderTest +{ + private static final ArrayNode ARRAY1 = JsonNodeFactory.instance.arrayNode(); + + static + { + ARRAY1.add("element1"); + ARRAY1.add("element2"); + } + + private JsonProvider provider = new JacksonJsonNodeJsonProvider(); + + @Test + void newJsonArray_emptyJsonArray() + { + assertEquals(JsonNodeFactory.instance.arrayNode(), provider.newJsonArray()); + } + + @Test + void newJsonArray_sourceJsonArray_copy() + { + Object result = provider.newJsonArray(ARRAY1); + assertEquals(ARRAY1, result); + assertNotSame(ARRAY1, result); + } + +} diff --git a/pom.xml b/pom.xml index f5bab1d..f52b736 100644 --- a/pom.xml +++ b/pom.xml @@ -175,7 +175,6 @@ UTF-8 public false - ${project.basedir}/src/main/javadoc/stylesheet.css