package alien4cloud.utils.jackson; import java.io.IOException; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.BeanDescription; 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.deser.ContextualDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.google.common.collect.Maps; /** * Custom de serializer that de-serialize map from an array of {@link MapEntry}. */ public class JSonMapEntryArrayDeSerializer extends StdDeserializer<Map<?, ?>> implements ContextualDeserializer { private static final long serialVersionUID = 1L; protected JSonMapEntryArrayDeSerializer() { super(Map.class); } private JavaType keyType; private JavaType valueType; public JSonMapEntryArrayDeSerializer(JavaType keyType, JavaType valueType) { super(Map.class); this.keyType = keyType; this.valueType = valueType; } @Override public Map<?, ?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { // deserialize the map from array of map entries Map<Object, Object> map = Maps.newHashMap(); JavaType mapEntryType = TypeFactory.defaultInstance().constructSimpleType(MapEntry.class, new JavaType[] { keyType, valueType }); JavaType mapEntryArrayType = TypeFactory.defaultInstance().constructArrayType(mapEntryType); ObjectCodec codec = jp.getCodec(); if (codec == null) { throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into Java objects"); } MapEntry<Object, Object>[] entries = codec.readValue(jp, mapEntryArrayType); for (MapEntry<Object, Object> entry : entries) { map.put(entry.getKey(), entry.getValue()); } return map; } @Override public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { if (ConditionalEnabledHelper.isEnabled(ctxt, property)) { return new JSonMapEntryArrayDeSerializer(property.getType().getKeyType(), property.getType().getContentType()); } BeanDescription beanDesc = ctxt.getConfig().introspect(property.getType()); JsonDeserializer<?> deserializer = ctxt.getFactory().createMapDeserializer(ctxt, (MapType) property.getType(), beanDesc); if (deserializer instanceof ContextualDeserializer) { return ((ContextualDeserializer) deserializer).createContextual(ctxt, property); } return deserializer; } }