我正在使用第 3 方服务,它输出 JSON,我试图将其反序列化为 Java POJO。无法更改 JSON 服务,我使用的是 Java 8 和 Jackson 2.4。
这是我的问题的简化版本。我在下面有一个接口(interface)和两个具体类:
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 类型。如何才能让我 jackson 做到这一点?
最佳答案
它可以通过自定义实现 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 .
关于java - 在不使用 @JsonTypeInfo 的情况下使用 Jackson 反序列化为多态集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38490969/