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

Невозможно с (de) сериализовать Список с полиморфными элементами в Джексоне

У меня есть вопрос (де) сериализации JSON, который не определен мной.

Вот несколько кодов и JSON, которые объясняют проблему:

код:

public static class Base {
    public String klass = "base";
}

public static class SubBase extends Base {
}

public static class Sub1 extends SubBase {
    public Sub1() {
        klass = "Sub1";
    }
}

public static class Sub2 extends SubBase {
    public Sub2() {
        klass = "Sub2";
    }
}

public static class Holder {
    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_ARRAY, property="type")
    @JsonSubTypes({@JsonSubTypes.Type (name = "sub1", value = Sub1.class),@JsonSubTypes.Type(name = "sub2", value = Sub2.class)})
    public List<Base> items = new ArrayList<Base>();
}


Holder holder = new Holder();
holder.items.add(new Sub1());
holder.items.add(new Sub1());

mapper.writeValueAsString(holder);

производит

{"items":[["sub1",{"klass":"Sub1"}],["sub1",{"klass":"Sub1"}]]}

Если я изменю аннотацию JsonTypeInfo на

    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT, property="type")

производит

{"items":[{"sub1":{"klass":"Sub1"}},{"sub1":{"klass":"Sub1"}}]}

Пока все хорошо:)

Однако JSON, который я получаю с сервера, имеет немного другую структуру:

{"type":"sub1", "items":[{"klass":"Sub1"},{"klass":"Sub1"}]}

Где тип массива элементов определяется в свойстве "type" (обратите внимание, что все элементы в массиве "items" относятся к одному классу).
Я просто не могу понять, какую комбинацию JsonTypeInfo использовать, чтобы это произошло. Я попытался установить "include" в ".EXTERNAL_PROPERTY", но это не работает.
Дессериализация с использованием этого включения дает мне "Исключение в потоке" main "org.codehaus.jackson.JsonGenerationException: Невозможно записать имя поля, ожидая значения" сообщение об ошибке.

Мой вопрос: какую аннотацию мне нужно использовать, чтобы "{" type ":" sub1 "," items ": [{" klass ":" Sub1 "}, {" klass ":" Sub1 "} ]} 'заполнит массив "items" всеми экземплярами Sub1 на основе свойства "type" владельца?
Если это просто невозможно, есть ли другой способ сделать это (без необходимости использования специального сериализатора для Holder, пользовательский сериализатор только для массива "items" будет в порядке)?

Спасибо!

4b9b3361

Ответ 1

Невозможно отобразить JSON, который вы показываете автоматически; это не один из четырех типов, поддерживаемых Jackson.

Если вы не можете заставить сервер создавать более стандартную структуру (для которой существует автоматическая поддержка), вам нужно будет написать собственный десериализатор; или выполнить привязку данных в два этапа, сначала в промежуточную легко отображаемую структуру (например, JsonNode или Map), а затем из нее в желаемую структуру вручную извлекать тип, используя это (например, с ObjectMapper.convertValue(object, resultType).