Я пытаюсь работать через учебное руководство от Программиста Bruce, который, как предполагается, позволяет десериализацию полиморфного JSON.
Полный список может быть найден здесь учебные руководства Программиста Bruce (Большой материал btw)
Я работал через первые пять без проблем, но я наткнулся на препятствие на последнем (Пример 6), который, конечно, является тем, который я действительно должен получить работу.
Я получаю следующую ошибку во время компиляции
Метод readValue (JsonParser, Класс) в типе ObjectMapper не применим для аргументов (ObjectNode, Класс)
и это вызывается блоком кода
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> elementsIterator =
root.getFields();
while (elementsIterator.hasNext())
{
Entry 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 (корень, animalClass);
Кто-либо столкнулся с этим прежде и если так, был там решением?
Я ценил бы любую справку, любой может благодарить заранее Jon D.
Как обещано, я помещаю пример для того, как использовать аннотации для сериализирования/десериализовывания полиморфных объектов, я основывал этот пример в Animal
класс из учебного руководства, которое Вы читали.
, В первую очередь, Ваш 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;
}
, Как Вы видите, нет ничего специального для Cat
и Dog
, единственный, которые знают о них, abstract
класс Animal
, поэтому при десериализации, Вы будете нацелены к [1 111], и эти ObjectMapper
возвратит фактический экземпляр, как Вы видите в следующем тесте:
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
Hope это помогает,
Jose Luis
Простой способ включить полиморфную сериализацию / десериализация через библиотеку Jackson состоит в том, чтобы глобально настроить картопостроитель объекта Jackson (jackson.databind. ObjectMapper) для добавления информации, такой как тип реального класса, для определенных видов классов, таких как абстрактные классы.
, Чтобы сделать это, просто удостоверьтесь, что Ваш картопостроитель настроен правильно. Например:
Опция 1: Поддерживайте полиморфную сериализацию / десериализация для абстрактных классов (и Объект ввел классы)
jacksonObjectMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
Опция 2: Поддерживайте полиморфную сериализацию / десериализация для абстрактных классов (и Объект ввел классы), и массивы тех типов.
jacksonObjectMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
Ссылка: https://github.com/FasterXML/jackson-docs/wiki/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");
вместо [1 111]
new SimpleModule("PolymorphicAnimalDeserializerModule",
new Version(1, 0, 0, null));
и у Животного десериализовывает () функцию, делает ниже изменений
//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. Если это все еще жалуется на поля класса. Используйте тот же формат в качестве в json для имен полей (с "_" - подчеркивание). поскольку это
//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;
}