ContextualDeserializer for mapping JSON to different types of maps with Jackson

前端 未结 1 1304
长发绾君心
长发绾君心 2021-01-06 21:25

This JSON snippet should be mapped to a Java-Objects that contains a cars field of type Map and a bikes field of ty

相关标签:
1条回答
  • 2021-01-06 22:03

    Here's how I might approach it.

    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.codehaus.jackson.JsonNode;
    import org.codehaus.jackson.JsonParser;
    import org.codehaus.jackson.JsonProcessingException;
    import org.codehaus.jackson.Version;
    import org.codehaus.jackson.map.BeanProperty;
    import org.codehaus.jackson.map.ContextualDeserializer;
    import org.codehaus.jackson.map.DeserializationConfig;
    import org.codehaus.jackson.map.DeserializationContext;
    import org.codehaus.jackson.map.JsonDeserializer;
    import org.codehaus.jackson.map.JsonMappingException;
    import org.codehaus.jackson.map.ObjectMapper;
    import org.codehaus.jackson.map.module.SimpleModule;
    
    public class Foo
    {
      public static void main(String[] args) throws Exception
      {
        EmptyStringAsMapDeserializer<Map<String, ?>> emptyStringAsMapDeserializer = 
            new EmptyStringAsMapDeserializer<Map<String, ?>>(null, new ObjectMapper());
    
        SimpleModule module = new SimpleModule("ThingsDeserializer", Version.unknownVersion());
        module.addDeserializer(Map.class, emptyStringAsMapDeserializer);
    
        ObjectMapper mapper = new ObjectMapper().withModule(module);
    
        Person person = mapper.readValue(new File("input.json"), Person.class);
        System.out.println(mapper.writeValueAsString(person));
      }
    }
    
    class Person
    {
      public int id;
      public String name;
      public Map<String, Car> cars;
      public Map<String, Bike> bikes;
    }
    
    class Car
    {
      public String color;
      public String buying_date;
    }
    
    class Bike
    {
      public String color;
    }
    
    class EmptyStringAsMapDeserializer<T>
        extends JsonDeserializer<Map<String, ?>>
        implements ContextualDeserializer<Map<String, ?>>
    {
      private Class<?> targetType;
      private ObjectMapper mapper;
    
      EmptyStringAsMapDeserializer(Class<?> targetType, ObjectMapper mapper)
      {
        this.targetType = targetType;
        this.mapper = mapper;
      }
    
      @Override
      public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig config, BeanProperty property)
          throws JsonMappingException
      {
        return new EmptyStringAsMapDeserializer<Object>(property.getType().containedType(1).getRawClass(), mapper);
      }
    
      @Override
      public Map<String, ?> deserialize(JsonParser jp, DeserializationContext ctxt)
          throws IOException, JsonProcessingException
      {
        JsonNode node = jp.readValueAsTree();
        if ("".equals(node.getTextValue()))
          return new HashMap<String, Object>();
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(node, mapper.getTypeFactory().constructMapType(Map.class, String.class, targetType));
      }
    }
    

    The generic type parameters might be a little out of order. I did a bit of quick copy-pasting.

    0 讨论(0)
提交回复
热议问题