ContextualDeserializer for mapping JSON to different types of maps with Jackson

前端 未结 1 1258
长发绾君心
长发绾君心 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> emptyStringAsMapDeserializer = 
            new EmptyStringAsMapDeserializer>(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 cars;
      public Map bikes;
    }
    
    class Car
    {
      public String color;
      public String buying_date;
    }
    
    class Bike
    {
      public String color;
    }
    
    class EmptyStringAsMapDeserializer
        extends JsonDeserializer>
        implements ContextualDeserializer>
    {
      private Class targetType;
      private ObjectMapper mapper;
    
      EmptyStringAsMapDeserializer(Class targetType, ObjectMapper mapper)
      {
        this.targetType = targetType;
        this.mapper = mapper;
      }
    
      @Override
      public JsonDeserializer> createContextual(DeserializationConfig config, BeanProperty property)
          throws JsonMappingException
      {
        return new EmptyStringAsMapDeserializer(property.getType().containedType(1).getRawClass(), mapper);
      }
    
      @Override
      public Map deserialize(JsonParser jp, DeserializationContext ctxt)
          throws IOException, JsonProcessingException
      {
        JsonNode node = jp.readValueAsTree();
        if ("".equals(node.getTextValue()))
          return new HashMap();
        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)
    提交回复
    热议问题