Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to Jackson's JsonNode #3

Merged
merged 1 commit into from Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions jsonmerge-core/pom.xml
Expand Up @@ -35,6 +35,7 @@
<json-path.version>2.7.0</json-path.version>
<json-org.version>20220320</json-org.version>
<gson.version>2.9.1</gson.version>
<jackson.version>2.13.3</jackson.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -73,5 +74,12 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>

</dependencies>
</project>
@@ -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);
}

}
@@ -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));
});
}

}
@@ -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);
}

}
1 change: 0 additions & 1 deletion pom.xml
Expand Up @@ -175,7 +175,6 @@
<encoding>UTF-8</encoding>
<show>public</show>
<aggregate>false</aggregate>
<stylesheetfile>${project.basedir}/src/main/javadoc/stylesheet.css</stylesheetfile>
</configuration>
<executions>
<execution>
Expand Down