2017-01-10 3 views
0

Я хочу десериализовать полиморфные подтипы уровня 2 с помощью аннотаций Джексона. В основном я хочу, чтобы преобразовать следующий JSON в XML с помощью JSON аннотаций и Jacksons следующихDeserialize многоуровневые полиморфные подтипы с использованием аннотаций Джексона

{ 
    "mainSet": { 
    "name": "bla bla", 
    "myItems": [ 
     { 
     "MySubItem": { 
      "id": 1, 
      "name": "Value1", 
      "itemAProperty1": "Some stuff", 
      "itemAProperty2": "Another property value", 
      "type": "MySubItemA" 
     } 
     }, 
     { 
     "MySubItem": { 
      "id": 2, 
      "name": "Value2", 
      "itemBProperty1": 1000, 
      "itemBProperty2": "B property", 
      "type": "MySubItemB" 
     } 
     } 
    ] 
    } 
} 

И Final Xml я хочу

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<mainTag schemaVersion="1" xmlns="http://www.utiba.com/xml/ns/brms/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <name>bla bla</name> 
    <MySubItem xsi:type="MySubItemA" id="1" name="value1" itemAProperty1="Some stuff" itemAProperty2="Another property value"/> 
    <MySubItem xsi:type="MySubItemB" id="2" name="value2" itemAProperty1=1000 itemAProperty2="B Property"/> 
</mainTag> 

Я следующий набор классов - Основной класс

public abstract class MyItem { 

private int id; 
private String name; 
//getter and setter 
} 

Имеет абстрактный подкласс

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "MySubItem") 
@XmlSeeAlso({ 
    MySubItemA.class, 
    MySubItemB.class, 
    MySubItemC.class 
}) 
    public abstract class MySubItem extends MyItem { 

    private String itemAProperty1; 
    private String itemAProperty2; 
    //getter and setter 
    } 

И MySubItem имеют конкретные subclases сказать MySubItemA, MySubItemB, MySubItemC

Теперь, наконец, мы создаем класс клиента, который содержит список объектов абстрактного класса

import java.util.ArrayList; 
    import java.util.List; 

    public class MainSet{ 
    @XmlElements({ 
     @XmlElement(name = "MysubItem", type = MySubItem.class), 
    }) 
    private List<MyItem> myItems; 

     public List<MyItem> getMyItems() { 
     return this.myItems; 
    } 
    } 

Я пытался создать подмешать классы для MyItem как

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="itemType") 
@JsonSubTypes({ 
    @Type(MySubItem.class) 
}) 

и для и MySubItem

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="type") 
@JsonSubTypes({ 
    @Type(MySubItemA.class) 
    @Type(MySubItemB.class) 
    @Type(MySubItemC.class) 
}) 

Ошибки я получаю:

Error parsing JSON from client: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of MySubItem, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information 
at [Source: [email protected]; line: 1, column: 498] (through reference chain: bla bla class ["mainSet"]->com.bla.bla["myItems"]) 

ВЫПУСК: создать класс подмешать для списка myItems, имеющий 2 уровня иерархии абстрактных подклассов

ответ

0

Несколько уровней иерархии полиморфного типа не поддерживаются Джексон API.

Вы можете посмотреть на: https://github.com/FasterXML/jackson-databind/issues/374

Так что вам нужно сделать, это:

Пожалуйста, создайте десериализатор (для MySubItem.class сказать MySubItemDeserializerMixin.class) для и настройки, что jsonMapper как мы сделать для других классов Mixin.

mapper.addMixInAnnotations(MySubItem.class, MySubItemDeserializerMixin.class); 

MySubItemDeserializerMixin.java будет выглядеть так:

@JsonDeserialize(using = MySubItemDeserializer.class) 
public abstract class MySubItemDeserializerMixin{ 
} 

Кроме того, необходимо будет создать десериализатор (MySubItemDeserializer) для MySubItem, как указано в MySubItemDeserializerMixin.java.

Теперь вам нужно создать MySubItemMixin.Java, который будет выглядеть следующим образом:

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="type") 
@JsonSubTypes({ 
@Type(MySubItemA.class) 
@Type(MySubItemB.class) 
@Type(MySubItemC.class) 
}) 

В MySubItemDeserializer вы могли бы сделать что-то вроде:

@Override 
public MySubItem deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 

    JsonNode node = jsonParser.getCodec().readTree(jsonParser); 

    ObjectMapper jsonMapper = new ObjectMapper(); 

    // Omit null values from the JSON. 
    jsonMapper.setSerializationInclusion(Include.NON_NULL); 

    // Treat received empty JSON strings as null Java values. 
    // Note: doesn't seem to work - using custom deserializer through module 
    // below instead. 
    jsonMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); 

    jsonMapper.addMixInAnnotations(MySubItem.class, MySubItemMixin.class); 

    // Enable interpretation of JAXB annotations on our beans (e.g. for 
    // resolving ID/IDREF references). 
    jsonMapper.registerModule(new JaxbAnnotationModule()); 

    MySubItem condition = jsonMapper.readValue(node.toString(), MySubItem.class); 

    } 

Хоупа, который решает свои проблемы.

Благодарности & Привет

Накул Vashishth

+0

Спасибо Nakul за решение .. Это сработало для меня :) –

0

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

@JsonSubTypes({ 
    MySubItemA.class, 
    MySubItemB.class, 
    MySubItemC.class 
}) 
+0

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

+0

Я также попытался создать класс mixin для * MainSet *, добавив '@XmlElement (name =" mySubItem ", type = MySubItemA.class), @ XmlElement (name =" mySubItem ", type = MySubItemB.class), @ XmlElement (name = "mySubItem", type = MySubItemC.class) ', но в этом случае он подбирает последнюю для всех подтипов A, B, C. –

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