将Jackson与JSON反序列化成多态types – 一个完整的例子给我一个编译错误

我试图通过一个程序员布鲁斯的教程,是应该允许反序列化的多态JSON。

完整的列表可以在这里find程序员布鲁斯教程 (伟大的东西btw)

我已经完成了前五项,但没有遇到任何问题,但是最后一项(例6)遇到了困难,这当然是我真正需要的工作。

我在编译时收到以下错误

ObjectMappertypes中的readValue(JsonParser,Class)方法不适用于参数(ObjectNode,Class)

这是由大量的代码引起的

public Animal deserialize( JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = (ObjectMapper) jp.getCodec(); ObjectNode root = (ObjectNode) mapper.readTree(jp); Class<? extends Animal> animalClass = null; Iterator<Entry<String, JsonNode>> elementsIterator = root.getFields(); while (elementsIterator.hasNext()) { Entry<String, JsonNode> 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); } } 

具体由行

返回mapper.readValue(root,animalClass);

有没有人遇到过,如果是的话,有没有解决scheme?

我会很感激任何帮助任何人可以提前致谢Jon D.

如所承诺的,我正在举例说明如何使用批注来序列化/反序列化多态对象,我从您正在阅读的教程的Animal类中的示例中find。

首先你的Animal类与Json注解的子类。

 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "Dog"), @JsonSubTypes.Type(value = Cat.class, name = "Cat") } ) public abstract class Animal { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 

然后你的子类, DogCat

 public class Dog extends Animal { private String breed; public Dog() { } public Dog(String name, String breed) { setName(name); setBreed(breed); } public String getBreed() { return breed; } public void setBreed(String breed) { this.breed = breed; } } public class Cat extends Animal { public String getFavoriteToy() { return favoriteToy; } public Cat() {} public Cat(String name, String favoriteToy) { setName(name); setFavoriteToy(favoriteToy); } public void setFavoriteToy(String favoriteToy) { this.favoriteToy = favoriteToy; } private String favoriteToy; } 

正如你所看到的,猫和狗没有什么特别之处,唯一知道它们的就是abstractAnimal ,所以当反序列化时,你将瞄准AnimalObjectMapper将返回实际的实例,就像你看到的以下testing:

 public class Test { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); Animal myDog = new Dog("ruffus","english shepherd"); Animal myCat = new Cat("goya", "mice"); try { String dogJson = objectMapper.writeValueAsString(myDog); System.out.println(dogJson); Animal deserializedDog = objectMapper.readValue(dogJson, Animal.class); System.out.println("Deserialized dogJson Class: " + deserializedDog.getClass().getSimpleName()); String catJson = objectMapper.writeValueAsString(myCat); Animal deseriliazedCat = objectMapper.readValue(catJson, Animal.class); System.out.println("Deserialized catJson Class: " + deseriliazedCat.getClass().getSimpleName()); } catch (Exception e) { e.printStackTrace(); } } } 

运行Test类后输出:

{"@type":"Dog","name":"ruffus","breed":"english shepherd"}

Deserialized dogJson Class: Dog

{"@type":"Cat","name":"goya","favoriteToy":"mice"}

Deserialized catJson Class: Cat

希望这可以帮助,

何塞·路易斯

通过Jackson库启用多态序列化/反序列化的一个简单方法是全局configurationJackson对象映射器(jackson.databind.ObjectMapper),为特定种类的类(如抽象类)添加信息,例如具体类types。

要做到这一点,只要确保您的映射器configuration正确。 例如:

选项1:支持抽象类(和对象types化类)的多态序列化/反序列化

 jacksonObjectMapper.enableDefaultTyping( ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); 

选项2:支持抽象类(和对象types化类)的多态序列化/反序列化,以及这些types的数组。

 jacksonObjectMapper.enableDefaultTyping( ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS); 

参考: http : //wiki.fasterxml.com/JacksonPolymorphicDeserialization

如果使用fasterxml,

这些变化可能是需要的

 import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.node.ObjectNode; 

主要方法 –

使用

 SimpleModule module = new SimpleModule("PolymorphicAnimalDeserializerModule"); 

代替

 new SimpleModule("PolymorphicAnimalDeserializerModule", new Version(1, 0, 0, null)); 

并在Animal deserialize()函数中做出以下更改

 //Iterator<Entry<String, JsonNode>> elementsIterator = root.getFields(); Iterator<Entry<String, JsonNode>> elementsIterator = root.fields(); //return mapper.readValue(root, animalClass); return mapper.convertValue(root, animalClass); 

这适用于fasterxml.jackson。 如果还是抱怨class级领域的话。 使用与json中字段名称相同的格式(使用“_”–underscore)。 为此
//mapper.setPropertyNamingStrategy(new CamelCaseNamingStrategy()); 可能不被支持。

 abstract class Animal { public String name; } class Dog extends Animal { public String breed; public String leash_color; } class Cat extends Animal { public String favorite_toy; } class Bird extends Animal { public String wing_span; public String preferred_food; }