Подтвердить что ты не робот

Библиотека Jackson JSON: как создать экземпляр класса, содержащего абстрактные поля

Я хочу преобразовать строку JSON в объект java, но класс этого объекта содержит абстрактные поля, которые Джексон не может создать, и не создает объект. Каков самый простой способ рассказать об определенной по умолчанию реализации абстрактного класса, например

setDefault(AbstractAnimal.class, Cat.class);

или принять решение о классе реализации на основе имени атрибута JSON, например. для объекта JSON:

{
    ...
    cat: {...}
    ...
}

Я бы просто сказал:

setImpl("cat", Cat.class);


Я знаю, что в Jackson можно встроить информацию о классе внутри JSON, но я не хочу усложнять формат JSON, который я использую. Я хочу решить, какой класс использовать, просто установив класс реализации по умолчанию или имя атрибута ('cat') - как в библиотеке XStream, где вы пишете:

xStream.alias("cat", Cat.class);

Есть ли способ сделать это, особенно в одной строке, или требуется какой-то еще код?

4b9b3361

Ответ 1

Существует несколько способов; до версии 1.8, возможно, самый простой способ:

@JsonDeserialize(as=Cat.class)
public abstract class AbstractAnimal { ... }

чтобы принять решение на основе атрибута, лучше всего использовать с помощью @JsonTypeInfo, который автоматически встраивается (при записи) и использует информацию о типе.

Существует несколько типов информации типа (имя класса, логическое имя типа), а также механизмы включения (as-included-property, as-wrapper-array, as-wrapper-object). Эта страница: https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization объясняет некоторые из концепций.

Ответ 2

Полноценный ответ с очень ясным примером можно найти здесь: fooobar.com/questions/195692/...

Джексон ссылается на это как на полиморфную десериализацию.

Это определенно помогло мне с моей проблемой. У меня был абстрактный класс, который я сохранял в базе данных, и мне нужно было его развязать с конкретным экземпляром класса (понятно).

Он покажет вам, как правильно аннотировать родительский абстрактный класс и как обучать джексону, как выбрать среди доступных кандидатов подкласса во время выполнения при размашировании.

Ответ 3

проблема может быть решена с помощью аннотации @JsonDeserialize для абстрактного класса, относящейся к исключениям Джексона. Проблемы и решения https://www.baeldung.com/jackson-exception

Ответ 4

Если вы не хотите загрязнять свой JSON дополнительными полями или свои классы аннотациями, вы можете написать очень простой модуль и десериализатор, который использует нужный подкласс по умолчанию. Это несколько строк из-за некоторого стандартного кода, но это все еще относительно просто.

class AnimalDeserializer extends StdDeserializer<Animal> {
    public AnimalDeserializer() {
        super(Animal.class);
    }

    public Animal deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
        return jsonParser.readValueAs(Cat.class);
    }
}

class AnimalModule extends SimpleModule {
    {
        addDeserializer(Animal.class, new AnimalDeserializer());
    }
}

Затем зарегистрируйте этот модуль для ObjectMapper и для него (Zoo - это контейнерный класс, имеющий поле Animal).

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new AnimalModule());
return objectMapper.readValue(json, Zoo.class);