Джексон не включает информацию о типе для полей во время сериализации.

Я пытаюсь сериализовать объект в json, используя jackson 2.6.3. Я хочу включить информацию о типе в сериализованный json. Это не работает для членов, вложенных в этот класс.

Вот тестовый код.

public class Test {

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {

}
@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteA implements A {

}

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteB.class)})
interface B {

}
@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteB implements B {
    A a;
    public A getA() {
        return a=new ConcreteA();
    }
}

@org.junit.Test
public void testSerialisation() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    System.out.println(objectMapper.writeValueAsString(new ConcreteB()));
}
}

JSON, преобразованный Джексоном,

{"@class":"Test$ConcreteB","a":{}}

Обратите внимание, что он не включает информацию о типе для поля «a». Информация о типе включается при сериализации только A.

{"@class":"Test$ConcreteA"} 

ОБНОВЛЕНИЕ: Вот объяснение и решение от jackson dev для проблемы https://github.com/FasterXML/jackson-databind/issues/1015


person Akshay Sharma    schedule 21.11.2015    source источник
comment
Зачем вам нужна информация о типе для «a» при сериализации B? Когда вы десериализуете в «B», тип «a» будет задан B.   -  person jbarrueta    schedule 21.11.2015
comment
A представляет собой интерфейс и может иметь множество реализаций. Как узнать, какой тип десериализовать без информации о типе?   -  person Akshay Sharma    schedule 21.11.2015
comment
Я вижу проблему сейчас, также получил это работает.   -  person jbarrueta    schedule 21.11.2015


Ответы (2)


Кажется, вы были довольно близки, все, что вам нужно добавить, это способ сообщить Джексону, как обращаться с вашим типом интерфейса.

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "@class")
@JsonSubTypes({
        @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {
}

Таким образом, добавление @JsonTypeInfo к вашему интерфейсу добавит информацию о типе в свойстве, которое вы можете настроить, чтобы оно было тем, которое вы ожидаете, в этом случае я выбрал @class.

Вывод Json, который я получил из своего примера:

{"@class":"com.company.jackson.Test$ConcreteB","a":{"@type":"Test$ConcreteA"}}

Надеюсь, поможет,

Хосе Луис

person jbarrueta    schedule 21.11.2015
comment
добавление только @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) в A работает. Спасибо за указатель. - person Akshay Sharma; 21.11.2015
comment
Рад слышать, что это сработало и помогло вам, не могли бы вы принять ответ? Спасибо! - person jbarrueta; 21.11.2015
comment
Я хотел иметь полное имя класса в @class. Приведенное выше решение помещает имя типа в @class. Использование JsonTypeInfo.Id.CLASS вместо этого помещает имя класса интерфейса, а не реализацию. - person Akshay Sharma; 22.11.2015
comment
Когда мы применяем его в массивах, Джексон не применяет @class к сгенерированному JSON. Любые предложения, пожалуйста? - person Raffael Bechara Rameh; 11.05.2017

Я столкнулся с той же проблемой. Я импортировал неправильный класс ObjectMapper.

В идеале это должен быть jackson-databind.jar.

com.fasterxml.jackson.databind.ObjectMapper

но я импортировал jackson-mapper-asl.jar

org.codehaus.jackson.map.ObjectMapper
person NIrav Modi    schedule 23.04.2018