Jackson deserialization of type with different objects

前端 未结 4 1538
清酒与你
清酒与你 2020-12-06 02:21

I have a result from a web service that returns either a boolean value or a singleton map, e.g.

Boolean result:

{
    id: 24428,
    rated: false
}
<         


        
4条回答
  •  遥遥无期
    2020-12-06 02:49

    I found a nice article on the subject: http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html

    I think that the approach of parsing into object, is possibly problematic, because when you send it, you send a string. I am not sure it is an actual issue, but it sounds like some possible unexpected behavior. example 5 and 6 show that you can use inheritance for this.

    Example:

    Example 6: Simple Deserialization Without Type Element To Container Object With Polymorphic Collection

    Some real-world JSON APIs have polymorphic type members, but don't include type elements (unlike the JSON in the previous examples). Deserializing such sources into polymorphic collections is a bit more involved. Following is one relatively simple solution. (This example includes subsequent serialization of the deserialized Java structure back to input JSON, but the serialization is relatively uninteresting.)

    // input and output:
    //   {
    //     "animals":
    //     [
    //       {"name":"Spike","breed":"mutt","leash_color":"red"},
    //       {"name":"Fluffy","favorite_toy":"spider ring"},
    //       {"name":"Baldy","wing_span":"6 feet",
    //           "preferred_food":"wild salmon"}
    //     ]
    //   }
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    
    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.DeserializationContext;
    import org.codehaus.jackson.map.ObjectMapper;
    import org.codehaus.jackson.map.deser.StdDeserializer;
    import org.codehaus.jackson.map.module.SimpleModule;
    import org.codehaus.jackson.node.ObjectNode;
    
    import fubar.CamelCaseNamingStrategy;
    
    public class Foo
    {
      public static void main(String[] args) throws Exception
      {
        AnimalDeserializer deserializer = 
            new AnimalDeserializer();
        deserializer.registerAnimal("leash_color", Dog.class);
        deserializer.registerAnimal("favorite_toy", Cat.class);
        deserializer.registerAnimal("wing_span", Bird.class);
        SimpleModule module =
          new SimpleModule("PolymorphicAnimalDeserializerModule",
              new Version(1, 0, 0, null));
        module.addDeserializer(Animal.class, deserializer);
        
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(
            new CamelCaseNamingStrategy());
        mapper.registerModule(module);
    
        Zoo zoo = 
            mapper.readValue(new File("input_6.json"), Zoo.class);
        System.out.println(mapper.writeValueAsString(zoo));
      }
    }
    
    class AnimalDeserializer extends StdDeserializer
    {
      private Map> registry =
          new HashMap>();
    
      AnimalDeserializer()
      {
        super(Animal.class);
      }
    
      void registerAnimal(String uniqueAttribute,
          Class animalClass)
      {
        registry.put(uniqueAttribute, animalClass);
      }
    
      @Override
      public Animal deserialize(
          JsonParser jp, DeserializationContext ctxt) 
          throws IOException, JsonProcessingException
      {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        ObjectNode root = (ObjectNode) mapper.readTree(jp);
        Class animalClass = null;
        Iterator> elementsIterator = 
            root.getFields();
        while (elementsIterator.hasNext())
        {
          Entry element=elementsIterator.next();
          String name = element.getKey();
          if (registry.containsKey(name))
          {
            animalClass = registry.get(name);
            break;
          }
        }
        if (animalClass == null) return null;
        return mapper.readValue(root, animalClass);
      }
    }
    
    class Zoo
    {
      public Collection animals;
    }
    
    abstract class Animal
    {
      public String name;
    }
    
    class Dog extends Animal
    {
      public String breed;
      public String leashColor;
    }
    
    class Cat extends Animal
    {
      public String favoriteToy;
    }
    
    class Bird extends Animal
    {
      public String wingSpan;
      public String preferredFood;
    }
    

提交回复
热议问题