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を持っています。