Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f1087ae
commit 2c60b44
Showing
5 changed files
with
326 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 168 additions & 0 deletions
168
jsonmerge-core/src/main/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <a href="https://github.com/FasterXML/jackson">Jackson Project home</a> | ||
* @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<Entry<String, Object>> entrySet(final Object jsonObject) | ||
{ | ||
Iterator<Entry<String, JsonNode>> iterator = toJsonObject(jsonObject).fields(); | ||
Iterable<Entry<String, JsonNode>> 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<? super Object> action) | ||
{ | ||
toJsonArray(jsonArray).forEach(action); | ||
} | ||
|
||
@Override | ||
public boolean arrayContains(final Object jsonArray, final Object element) | ||
{ | ||
return stream(jsonArray).anyMatch(element::equals); | ||
} | ||
|
||
@Override | ||
public Stream<Object> stream(final Object jsonArray) | ||
{ | ||
Spliterator<JsonNode> spliterator = toJsonArray(jsonArray).spliterator(); | ||
return (Stream) StreamSupport.stream(spliterator, false); | ||
} | ||
|
||
} |
108 changes: 108 additions & 0 deletions
108
...erge-core/src/test/java/net/obvj/jsonmerge/JsonMergerJacksonJsonNodeJsonProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<ObjectNode> | ||
{ | ||
|
||
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)); | ||
}); | ||
} | ||
|
||
} |
42 changes: 42 additions & 0 deletions
42
...merge-core/src/test/java/net/obvj/jsonmerge/provider/JacksonJsonNodeJsonProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters