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

Джексон JsonTypeInfo.As.EXTERNAL_PROPERTY не работает должным образом

Я использую Джексона для разбора JSON, который я не контролирую. JSON выглядит так:

{
    "status":"0"
    "type":"type1"
    "info": {
       // additional fields
    }
}

Мой класс выглядит следующим образом

public class Response {
    private String status;
    private String type;
    private Info info
}

Подкласс Info, который я использую, зависит от свойства type, поэтому мое сопоставление для информации

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public abstract class Info {
    // some fields
}

Насколько я могу судить, это правильный способ использования информации о типе, когда отличительный элемент находится на том же уровне, что и элемент, который должен быть запущен. Но это не работает, я всегда получаю ту же ошибку:

com.fasterxml.jackson.databind.JsonMappingException: Неожиданный токен (END_OBJECT), ожидается FIELD_NAME: отсутствует свойство 'type', которое должно содержат идентификатор типа

Если я изменю EXTERNAL_PROPERTY на PROPERTY, я все равно получаю ту же ошибку. Непонятно ли мое понимание EXTERNAL_PROPERTI?

4b9b3361

Ответ 1

От Javadoc:

Механизм включения похож на PROPERTY, за исключением того, что свойство включал одноуровневое высшее по иерархии, т.е. как свойство братьев и сестер в тот же уровень, что и тип JSON для ввода. Обратите внимание, что этот выбор может быть только используется для свойств, а не для типов (классов). Попытка использовать его для классы приведут к включению стратегии базовой собственности.

Заметил, что can only be used for properties выделен полужирным. Источник: JsonTypeInfo.As.EXTERNAL_PROPERTY.

Итак, вы должны перенести все аннотации из класса Info в метод property Info или setInfo в классе Response.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = { @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
        @JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public void setInfo(Info info) {
    this.info = info;
}

Для меня также следует удалить свойство type из класса Response. Он будет генерироваться динамически во время процесса сериализации. В десериализации вам это не нужно, потому что Джексон заботится о типах. Ваш класс может выглядеть так:

class Response {

    private String status;
    private Info info;

    //getters, setters
}

Смотрите также этот вопрос: Связывание данных класса nSnest.