我正在使用第三方服务,它吐出JSON,我正在尝试反序列化为Java POJO。 JSON服务无法更改,我正在使用Java 8和Jackson 2.4。
以下是我的问题的简化版本。我有一个界面和下面的两个具体类:
public interface Animal {
}
public class Dog implements Animal {
public String bark;
}
public class Cat implements Animal {
public String meow;
}
我需要将以下JSON反序列化为List<Animal>
:
{
"animals": [
{
"bark":"bowwow"
},
{
"bark":"woofWoof"
},
{
"meow":"meeeOwww"
},
{
"meow":"hisssss"
}
]
}
我希望能够根据JSON中存在的meow属性(它是Cat)和bark属性(它是一个Dog)来确定具体的java类型。怎么能让杰克逊这样做呢?
答案 0 :(得分: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。