2015-07-10 4 views
1

У меня есть базовый класс и производный класс, как показано нижеДжексон сериализатору не показывает jsonInfoType после сериализации

@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, 
include =JsonTypeInfo.As.PROPERTY, property = "_type") 
@JsonSubTypes({ @JsonSubTypes.Type(value = BaseClass.class, 
name = "BaseClass")})  
public class BaseClass{ 
    private String a; 
} 


public class DerivedClass extends BaseClass{ 
    private String b; 
} 

Когда я сериализации Список BaseClass или Список DerivedClass Я не смог найти «_type» собственности в мой json. Но если я сериализую один экземпляр класса BaseClass или Derived, я могу увидеть свойство «_type».

Вот мой код Serializer.

public void serialize() throws Exception { 

    List<DerivedClass> bs = new ArrayList<DerivedClass>(); 
    bs.add(new DerivedClass()); 
    bs.add(new DerivedClass()); 
    String json = new ObjectMapper().writeValueAsString(bs); 
    LOG.debug(json); 
} 
+0

Я пробовал все решения при переполнении стека. Похоже, я делаю подобные вещи, но не уверен, почему я не мог получить тип. Я не хочу использовать mapper.writerWithType(). – ashy143

+0

Этого недостаточно, чтобы воспроизвести вашу проблему: пожалуйста, включите код, который вы используете для сериализации. Существуют общие проблемы, такие как попытка сериализовать «Список» полиморфных значений, где Java Type Erasure вызывает проблемы. Но без кода невозможно сказать, в чем проблема. – StaxMan

+0

@StaxMan Я добавил код для его сериализации. – ashy143

ответ

1

Проблема заключается в том, что из-за Java Тип Erasure, все Джексон видит List<Object>, в отношении типа. Поскольку Object не имеет @JsonTypeInfo, он не считает, что информация типа необходима - все значения ДОЛЖНЫ использовать один и тот же логический базовый тип, потому что во время десериализации нет экземпляров, и в качестве базовой линии следует использовать статически известную типизацию.

Итак, как вы это решаете?

Во-первых: мое предложение состоит в том, чтобы ВСЕГДА использовать простой, не общий POJO в качестве корневого значения и вообще избежать проблемы. Любой List оцененные свойства, полученные с POJO, будут иметь полную информацию о видах; корневых значений нет. Таким образом, я избегаю прямого сериализации List и Map с, а также генерических (параметризованных) POJO.

Однако, если вы все еще хотите решить более сложную проблему, это тоже выполнимо. Два основных способа:

Первый подход: создать класс удобства, как:

public class ListOfBase extends ArrayList<BaseClass> { } 
ListOfBase myList = new ListOfBase(); 
myList.add(...); 

и он будет работать, как и ожидалось, с информацией о типе

Второй подход: использование силы конкретного базового типа, через ObjectWriter: что-то вроде:

ObjectWriter w = mapper.writerFor(new TypeReference<List<BaseClass>>() { }); 
String json = w.writeValueAsString(myList); 

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

На самом деле существует и третий вариант: использовать массивы Java, а не коллекции. Массивы сильно типизированных, так что это будет работать:

BaseClass[] stuff = new BaseClass[] { value1, value2 }; 

, поскольку информация о типе сохраняется, в отличие от общих List с.

+0

Это работает, если я говорю Список list = new ArrayList (); – ashy143

+0

Нет: Тип Erasure означает, что Java не имеет понятия общих типов времени выполнения; в них содержатся только декларации класса. Вот почему 'TypeReference' работает: он создает фактический анонимный класс, который содержит объявления типов. Простое копирование не сохраняет дополнительную информацию о типе: базовый физический класс - это тот же самый «ArrayList», который является общим и фактические параметры типа теряются (они существуют только в источнике, байт-код просто содержит необходимые приведения). – StaxMan

Смежные вопросы