diff --git a/nitrite-jackson-mapper/pom.xml b/nitrite-jackson-mapper/pom.xml
index dd1c22012..d8d548ee4 100644
--- a/nitrite-jackson-mapper/pom.xml
+++ b/nitrite-jackson-mapper/pom.xml
@@ -40,7 +40,7 @@
slf4j-api
- com.fasterxml.jackson.core
+ tools.jackson.corejackson-databind
@@ -95,11 +95,6 @@
snakeyamltest
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jsr310
- test
-
diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/jackson/JacksonMapper.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/jackson/JacksonMapper.java
index bafbadbca..c96dc8d39 100644
--- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/jackson/JacksonMapper.java
+++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/jackson/JacksonMapper.java
@@ -16,31 +16,37 @@
package org.dizitart.no2.mapper.jackson;
+import static org.dizitart.no2.common.util.ValidationUtils.notNull;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.Module;
-import com.fasterxml.jackson.databind.*;
import org.dizitart.no2.NitriteConfig;
import org.dizitart.no2.collection.Document;
import org.dizitart.no2.common.mapper.NitriteMapper;
-import org.dizitart.no2.mapper.jackson.modules.NitriteIdModule;
import org.dizitart.no2.exceptions.ObjectMappingException;
import org.dizitart.no2.exceptions.ValidationException;
-
-import java.io.IOException;
-import java.util.*;
-
-import static org.dizitart.no2.common.util.ValidationUtils.notNull;
+import org.dizitart.no2.mapper.jackson.modules.NitriteIdModule;
+import tools.jackson.core.json.JsonReadFeature;
+import tools.jackson.databind.DatabindException;
+import tools.jackson.databind.JacksonModule;
+import tools.jackson.databind.JsonNode;
+import tools.jackson.databind.ObjectMapper;
+import tools.jackson.databind.json.JsonMapper;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* A {@link org.dizitart.no2.common.mapper.NitriteMapper} implementation that uses Jackson ObjectMapper to
* convert objects to and from Nitrite document.
- *
- * @since 4.0
- * @see org.dizitart.no2.common.mapper.NitriteMapper
+ *
* @author Anindya Chatterjee
+ * @see org.dizitart.no2.common.mapper.NitriteMapper
+ * @since 4.0
*/
public class JacksonMapper implements NitriteMapper {
+ private final List modules = new ArrayList<>();
private ObjectMapper objectMapper;
/**
@@ -50,30 +56,37 @@ public class JacksonMapper implements NitriteMapper {
*/
protected ObjectMapper getObjectMapper() {
if (objectMapper == null) {
- objectMapper = new ObjectMapper();
- objectMapper.setVisibility(
- objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
- .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
- .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
- .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
- objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
- objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
- objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.registerModule(new NitriteIdModule());
+ objectMapper = JsonMapper.builder()
+ .changeDefaultVisibility(visibilityChecker -> visibilityChecker
+ .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
+ .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
+ .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
+ )
+ .configure(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES, true)
+ .configure(JsonReadFeature.ALLOW_SINGLE_QUOTES, true)
+ .configure(JsonReadFeature.ALLOW_JAVA_COMMENTS, true)
+ .addModule(new NitriteIdModule())
+ .addModules(modules)
+ .build();
+ modules.clear();
}
return objectMapper;
}
/**
* Registers a Jackson module with the object mapper.
+ * Can only register modules as long as the underlying ObjectMapper is still un-initialized.
*
* @param module the Jackson module to register
+ *
* @throws ValidationException if the module is null
*/
- public void registerJacksonModule(Module module) {
+ public void registerJacksonModule(JacksonModule module) {
+ if (objectMapper != null) {
+ throw new IllegalStateException("Can not register modules after object mapper initialization.");
+ }
notNull(module, "module cannot be null");
- getObjectMapper().registerModule(module);
+ modules.add(module);
}
/**
@@ -86,11 +99,13 @@ public void registerJacksonModule(Module module) {
* already a Document, converts it to the target type. If the conversion fails,
* throws an ObjectMappingException.
*
- * @param source the source object to convert
- * @param type the target type to convert to
+ * @param source the source object to convert
+ * @param type the target type to convert to
* @param the type of the source object
* @param the type of the target object
+ *
* @return the converted object of the target type
+ *
* @throws ObjectMappingException if the conversion fails
*/
@Override
@@ -101,8 +116,9 @@ public Object tryConvert(Source source, Class type) {
try {
JsonNode node = getObjectMapper().convertValue(source, JsonNode.class);
- if (node == null)
+ if (node == null) {
return null;
+ }
if (node.isValueNode()) {
return getNodeValue(node);
@@ -115,11 +131,11 @@ public Object tryConvert(Source source, Class type) {
}
} catch (Exception e) {
throw new ObjectMappingException("Failed to convert object of type "
- + source.getClass() + " to type " + type, e);
+ + source.getClass() + " to type " + type, e);
}
throw new ObjectMappingException("Can't convert object to type " + type
- + ", try registering a jackson Module for it.");
+ + ", try registering a jackson Module for it.");
}
@Override
@@ -130,21 +146,23 @@ public void initialize(NitriteConfig nitriteConfig) {
* Converts a Nitrite Document to an object of the specified class type using
* Jackson ObjectMapper.
*
- * @param source the Nitrite Document to be converted
- * @param type the class type of the object to be converted to
+ * @param source the Nitrite Document to be converted
+ * @param type the class type of the object to be converted to
* @param the type of the object to be converted to
+ *
* @return the converted object of the specified class type
+ *
* @throws ObjectMappingException if there is an error in the object mapping
- * process
+ * process
*/
protected Target convertFromDocument(Document source, Class type) {
try {
return getObjectMapper().convertValue(source, type);
} catch (IllegalArgumentException iae) {
- if (iae.getCause() instanceof JsonMappingException) {
- JsonMappingException jme = (JsonMappingException) iae.getCause();
- if (jme.getMessage().contains("Cannot construct instance")) {
- throw new ObjectMappingException(jme.getMessage());
+ if (iae.getCause() instanceof DatabindException) {
+ DatabindException cause = (DatabindException) iae.getCause();
+ if (cause.getMessage().contains("Cannot construct instance")) {
+ throw new ObjectMappingException(cause.getMessage());
}
}
throw iae;
@@ -155,8 +173,9 @@ protected Target convertFromDocument(Document source, Class typ
* Converts the given source object to a Nitrite {@link Document} using
* Jackson's {@link ObjectMapper}.
*
- * @param source the source object to convert
+ * @param source the source object to convert
* @param the type of the source object
+ *
* @return the converted Nitrite {@link Document}
*/
protected Document convertToDocument(Source source) {
@@ -170,7 +189,7 @@ private T getNodeValue(JsonNode node) {
case NUMBER:
return (T) node.numberValue();
case STRING:
- return (T) node.textValue();
+ return (T) node.stringValue();
case BOOLEAN:
return (T) Boolean.valueOf(node.booleanValue());
default:
@@ -180,9 +199,7 @@ private T getNodeValue(JsonNode node) {
private Document readDocument(JsonNode node) {
Map objectMap = new LinkedHashMap<>();
- Iterator> fields = node.fields();
- while (fields.hasNext()) {
- Map.Entry entry = fields.next();
+ for (Map.Entry entry : node.properties()) {
String name = entry.getKey();
JsonNode value = entry.getValue();
Object object = readObject(value);
@@ -193,47 +210,34 @@ private Document readDocument(JsonNode node) {
}
private Object readObject(JsonNode node) {
- if (node == null)
- return null;
- try {
- switch (node.getNodeType()) {
- case ARRAY:
- return readArray(node);
- case BINARY:
- return node.binaryValue();
- case BOOLEAN:
- return node.booleanValue();
- case MISSING:
- case NULL:
- return null;
- case NUMBER:
- return node.numberValue();
- case OBJECT:
- case POJO:
- return readDocument(node);
- case STRING:
- return node.textValue();
- }
- } catch (IOException e) {
+ if (node == null) {
return null;
}
- return null;
+
+ switch (node.getNodeType()) {
+ case ARRAY:
+ return readArray(node);
+ case BINARY:
+ return node.binaryValue();
+ case BOOLEAN:
+ return node.booleanValue();
+ case NUMBER:
+ return node.numberValue();
+ case OBJECT:
+ case POJO:
+ return readDocument(node);
+ case STRING:
+ return node.stringValue();
+ default:
+ return null;
+ }
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private List readArray(JsonNode array) {
+ private List