2016-07-20 4 views
2

私はJava POJOにデシリアライズしようとしているJSONを吐き出すサードパーティのサービスを使用しています。 JSONサービスは変更できません。Java 8とJackson 2.4を使用しています。@JsonTypeInfoを使わずにジャクソンを使用してポリモーフィックコレクションにデシリアライズする

ここに私の問題の簡略化されたバージョンがあります。私はインターフェイスと下の2つの具体的なクラスがあります:私はに次のJSONをデシリアライズする必要が

public interface Animal { 

} 

public class Dog implements Animal { 

    public String bark; 

} 

public class Cat implements Animal { 

    public String meow; 

} 

List<Animal>:私は存在に基づいて、具体的なJavaの型を決定することができるようにしたい

{ 
     "animals": [ 
    { 
     "bark":"bowwow" 
    }, 
    { 
     "bark":"woofWoof" 
    }, 
    { 
     "meow":"meeeOwww" 
    }, 
    { 
     "meow":"hisssss" 
    } 
    ] 
} 

JSONのヤノのプロパティ(その猫)と樹皮のプロパティ(その犬)私はジャクソンをどうすればこのようにすることができますか

答えて

1

StdDeserializerのカスタム実装で実現することができます

public class UniquePropertyPolymorphicDeserializer<T> extends StdDeserializer<T> { 

    private Map<String, Class<? extends T>> registry; 

    public UniquePropertyPolymorphicDeserializer(Class<T> clazz) { 
     super(clazz); 
     registry = new HashMap<String, Class<? extends T>>(); 
    } 

    public void register(String uniqueProperty, Class<? extends T> clazz) { 
     registry.put(uniqueProperty, clazz); 
    } 

    @Override 
    public T deserialize(JsonParser p, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException { 

     Class<? extends T> clazz = null; 

     ObjectMapper mapper = (ObjectMapper) p.getCodec(); 
     ObjectNode obj = (ObjectNode) mapper.readTree(p); 
     Iterator<Entry<String, JsonNode>> elementsIterator = obj.fields(); 

     while (elementsIterator.hasNext()) { 
      Entry<String, JsonNode> element = elementsIterator.next(); 
      String name = element.getKey(); 
      if (registry.containsKey(name)) { 
       clazz = registry.get(name); 
       break; 
      } 
     } 

     if (clazz == null) { 
      throw ctxt.mappingException(
        "No registered unique properties found " 
        + "for polymorphic deserialization"); 
     } 

     return mapper.treeToValue(obj, clazz); 
    } 
} 

それは次のように使用することができます。詳細については

String json = "[{\"bark\":\"bowwow\"},{\"bark\":\"woofWoof\"},{\"meow\":\"meeeOwww\"},{\"meow\":\"hisssss\"}]"; 

UniquePropertyPolymorphicDeserializer<Animal> deserializer = 
    new UniquePropertyPolymorphicDeserializer<>(Animal.class); 

deserializer.register("bark", Dog.class); // if "bark" field is present, then it's a Dog 
deserializer.register("meow", Cat.class); // if "meow" field is present, then it's a Cat 

SimpleModule module = new SimpleModule("UniquePropertyPolymorphicDeserializer", 
     new Version(1, 0, 0, null, "com.example", "polymorphic-deserializer")); 
module.addDeserializer(Animal.class, deserializer); 

ObjectMapper mapper = new ObjectMapper(); 
mapper.registerModule(module); 

Animal[] animals = mapper.readValue(json, Animal[].class); 

を、見hereを持っています。

関連する問題