summaryrefslogtreecommitdiff
path: root/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java')
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java97
1 files changed, 97 insertions, 0 deletions
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java
new file mode 100644
index 00000000..5a081ec5
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonDeserializer.java
@@ -0,0 +1,97 @@
+package at.gv.egiz.eaaf.core.impl.json;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+
+/**
+ * Custom Jackson Deserializer to support generic types serialized as escaped
+ * Strings.
+ *
+ * <p>
+ * Code was an example from stack-overflow. <br>
+ * <br>
+ * This implementation checks if the generic class type is compatible to
+ * original interface, by using <code>Class.isAssignableFrom(...).</code>
+ * </p>
+ *
+ * @author tlenz
+ *
+ */
+public class EscapedJsonDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {
+ private final Map<JavaType, JsonDeserializer<Object>> cachedDeserializers = new HashMap<>();
+
+ @Override
+ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+ throw new IllegalArgumentException(
+ "EscapedJsonDeserializer should delegate deserialization for concrete class");
+
+ }
+
+ @Override
+ public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
+ throws JsonMappingException {
+ JavaType type = (ctxt.getContextualType() != null) ? ctxt.getContextualType()
+ : property.getMember().getType();
+ return cachedDeserializers.computeIfAbsent(type, (a) -> new InnerDeserializer(type));
+ }
+
+ private static class InnerDeserializer extends JsonDeserializer<Object> {
+ private final JavaType javaType;
+
+ private InnerDeserializer(JavaType javaType) {
+ this.javaType = javaType;
+ }
+
+ @Override
+ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException,
+ JsonProcessingException {
+ String string = p.readValueAs(String.class);
+ return ((ObjectMapper) p.getCodec()).readValue(string, javaType);
+ }
+
+ @Override
+ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
+ TypeDeserializer typeDeserializer)
+ throws IOException {
+ String str = p.readValueAs(String.class);
+ TreeNode root = ((ObjectMapper) p.getCodec()).readTree(str);
+ try {
+ Class clz = Class.forName(((TextNode) root.get("@class")).asText());
+
+ if (this.javaType.getRawClass().isAssignableFrom(clz)) {
+ // remove '@class' before deserialization because it's unknown in target class
+ if (root.isObject()) {
+ ((ObjectNode) root).remove("@class");
+ }
+
+ Object newJsonNode = p.getCodec().treeToValue(root, clz);
+ return newJsonNode;
+
+ } else {
+ throw new RuntimeException("Class looks supect because it does not match to interface.");
+
+ }
+
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+
+ }
+ }
+ }
+}