You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/11/20 07:32:02 UTC
[james-project] 19/41: JAMES-2813 use jackson built-in type
detection for polymorphic types
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 80bb1868e0b83c449c222d45f7b3d1e6e639047b
Author: Matthieu Baechler <ma...@apache.org>
AuthorDate: Fri Oct 18 16:40:40 2019 +0200
JAMES-2813 use jackson built-in type detection for polymorphic types
---
json/src/main/java/org/apache/james/json/DTO.java | 6 +++
.../apache/james/json/JsonGenericSerializer.java | 54 ++++++++++++++--------
2 files changed, 42 insertions(+), 18 deletions(-)
diff --git a/json/src/main/java/org/apache/james/json/DTO.java b/json/src/main/java/org/apache/james/json/DTO.java
index 2e0fbdb..34f84d4 100644
--- a/json/src/main/java/org/apache/james/json/DTO.java
+++ b/json/src/main/java/org/apache/james/json/DTO.java
@@ -19,5 +19,11 @@
package org.apache.james.json;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true)
public interface DTO {
+
+ String getType();
+
}
diff --git a/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
index e84630f..a1ed925 100644
--- a/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
+++ b/json/src/main/java/org/apache/james/json/JsonGenericSerializer.java
@@ -31,7 +31,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@@ -57,12 +59,15 @@ public class JsonGenericSerializer<T, U extends DTO> {
Function.identity()));
}
- public Optional<DTOModule<T, U>> findModule(T domainObject) {
- return Optional.ofNullable(domainClassToModule.get(domainObject.getClass()));
+ public Optional<U> convert(T domainObject) {
+ return Optional.ofNullable(domainClassToModule.get(domainObject.getClass()))
+ .map(module -> module.toDTO(domainObject));
}
- public Optional<DTOModule<T, U>> findModule(String type) {
- return Optional.ofNullable(typeToModule.get(type));
+ public Optional<T> convert(U dto) {
+ String type = dto.getType();
+ return Optional.ofNullable(typeToModule.get(type))
+ .map(module -> module.getToDomainObjectConverter().convert(dto));
}
}
@@ -98,35 +103,48 @@ public class JsonGenericSerializer<T, U extends DTO> {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
+ modules.stream()
+ .map(module -> new NamedType(module.getDTOClass(), module.getDomainObjectType()))
+ .forEach(objectMapper::registerSubtypes);
dtoConverter = new DTOConverter<>(modules);
}
public String serialize(T domainObject) throws JsonProcessingException {
- U dto = dtoConverter.findModule(domainObject)
- .map(module -> module.toDTO(domainObject))
+ U dto = dtoConverter.convert(domainObject)
.orElseThrow(() -> new UnknownTypeException("unknown type " + domainObject.getClass()));
return objectMapper.writeValueAsString(dto);
}
public T deserialize(String value) throws IOException {
- try {
- JsonNode jsonNode = objectMapper.readTree(value);
-
- JsonNode typeNode = jsonNode.path("type");
+ U dto = jsonToDTO(value);
+ return dtoConverter.convert(dto)
+ .orElseThrow(() -> new UnknownTypeException("unknown type " + dto.getType()));
+ }
- if (typeNode.isMissingNode()) {
- throw new InvalidTypeException("No \"type\" property found in the json document");
+ public U jsonToDTO(String value) throws IOException {
+ try {
+ JsonNode jsonTree = detectDuplicateProperty(value);
+ return parseAsPolymorphicDTO(jsonTree);
+ } catch (InvalidTypeIdException e) {
+ String typeId = e.getTypeId();
+ if (typeId == null) {
+ throw new InvalidTypeException("Unable to deserialize the json document", e);
+ } else {
+ throw new UnknownTypeException("unknown type " + typeId);
}
-
- String type = typeNode.asText();
- DTOModule<T, U> dtoModule = dtoConverter.findModule(type)
- .orElseThrow(() -> new UnknownTypeException("unknown type " + type));
- U dto = objectMapper.readValue(objectMapper.treeAsTokens(jsonNode), dtoModule.getDTOClass());
- return dtoModule.getToDomainObjectConverter().convert(dto);
} catch (MismatchedInputException e) {
throw new InvalidTypeException("Unable to deserialize the json document", e);
}
}
+ private JsonNode detectDuplicateProperty(String value) throws IOException {
+ return objectMapper.readTree(value);
+ }
+
+ @SuppressWarnings("rawtypes")
+ private U parseAsPolymorphicDTO(JsonNode jsonTree) throws IOException {
+ return (U) objectMapper.readValue(objectMapper.treeAsTokens(jsonTree), DTO.class);
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org