diff options
Diffstat (limited to 'eaaf_core_utils/src')
2 files changed, 170 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); + +      } +    } +  } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonSerializer.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonSerializer.java new file mode 100644 index 00000000..a79f4d90 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/json/EscapedJsonSerializer.java @@ -0,0 +1,73 @@ +package at.gv.egiz.eaaf.core.impl.json; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + + +/** + * Custom Jackson Serializer to support generic types and serialize them as + * escaped Strings. + *  + * <p> + * Code was an example from stack-overflow. + * </p> + *  + * @author tlenz + * + */ +public class EscapedJsonSerializer extends StdSerializer<Object> { +  private static final long serialVersionUID = 7334472154148003249L; + +  public EscapedJsonSerializer() { +    super((Class<Object>) null); +  } + +  @Override +  public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { +    StringWriter str = new StringWriter(); +    JsonGenerator tempGen = new JsonFactory().setCodec(gen.getCodec()).createGenerator(str); +    if (value instanceof Collection || value.getClass().isArray()) { +      tempGen.writeStartArray(); +      if (value instanceof Collection) { +        for (Object it : (Collection) value) { +          writeTree(gen, it, tempGen); +        } +      } else if (value.getClass().isArray()) { +        for (Object it : (Object[]) value) { +          writeTree(gen, it, tempGen); +        } +      } +      tempGen.writeEndArray(); +    } else { +      provider.defaultSerializeValue(value, tempGen); +    } +    tempGen.flush(); +    gen.writeString(str.toString()); +  } + +  @Override +  public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider serializers, +      TypeSerializer typeSer) throws IOException { +    StringWriter str = new StringWriter(); +    JsonGenerator tempGen = new JsonFactory().setCodec(gen.getCodec()).createGenerator(str); +    writeTree(gen, value, tempGen); +    tempGen.flush(); +    gen.writeString(str.toString()); +  } + +  private void writeTree(JsonGenerator gen, Object it, JsonGenerator tempGen) throws IOException { +    ObjectNode tree = ((ObjectMapper) gen.getCodec()).valueToTree(it); +    tree.set("@class", new TextNode(it.getClass().getName())); +    tempGen.writeTree(tree); +  } +} | 
