将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; } }
然后你的子类, Dog
和Cat
。
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; }
正如你所看到的,猫和狗没有什么特别之处,唯一知道它们的就是abstract
类Animal
,所以当反序列化时,你将瞄准Animal
, ObjectMapper
将返回实际的实例,就像你看到的以下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; }