2016-07-14 2 views
1

Я пытаюсь использовать один класс для сопоставления ответа, который я получаю из XML-запроса. Но xml-ответ отличается, в зависимости от некоторых настроек. Например, в ответе я получаю тег «владелец», который заполняется идентификатором объекта владельца. Если я добавлю параметр в свой запрос, я верну полные данные владельца, например, имя и фамилию. Теперь я хочу сопоставить тэг владельца либо переменной String, либо классу в зависимости от ответа.JAXB mapping 1 XML-тег для 2 переменных

Пример:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "domain") 
public class Response { 

    @XmlElement 
    private String name; 

    @XmlElement(name = "owner") 
    private String ownerSimple; 

    @XmlElement(name = "owner") 
    private Owner ownerComplex; 

} 

@XmlRootElement(name = "ownerc") 
public class OwnerC { 

    @XmlElement 
    int id; 

    @XmlElement 
    String fname; 

    @XmlElement 
    String lname; 
} 

XML на карте:

<response> 
    <name>Foo</name> 
    <owner>1234</owner> <!-- in this case it's only a id --> 
</response> 

<response> 
    <name>Foo</name> 
    <owner> <!-- in this case it's the owner class --> 
     <id>1234</id> 
     <fname>Jon</fname> 
     <lname>Doe</lname> 
    </owner> 
</response> 

ответ

1

Вы можете использовать @XmlAnyElement(lax=true) обрабатывать этот случай использования. Эта аннотация позволяет отменить маркер любого XML-объекта Java (DOM Node). На втором этапе, можно маршализацию в Node до требуемого объекта

Response

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "domain") 
public class Response { 

    @XmlElement 
    private String name; 

    @XmlAnyElement(lax=true) 
    private Object owner; 

    private String ownerSimple; 

    @XmlTransient 
    private Owner ownerComplex; 

Владелец

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "owner") 
public class Owner { 

    @XmlElement 
    int id; 

    @XmlElement 
    String fname; 

    @XmlElement 
    String lname; 

Unmarshaller

//Unmarshaller. Step 1 - Decodes Response and set a DOM Node at Owner 
//Important. Owner class must not be present in JAXB context, letting next step to decode the object properly. 
//Owner variable at Response class is annotated with @XmlTransient 
JAXBContext jaxbContext = JAXBContext.newInstance(Response.class); 
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
Response response = (Response) jaxbUnmarshaller.unmarshal(reader); 

//Unmarshaller. Step 2. Convert Node to the suitable Object 
//Considering both cases, simple-> String complex -> Owner Object.  
String ownerSimple = ((Node)response.getOwner()).getFirstChild().getNodeValue(); 
if (ownerSimple != null){ 
    response.setOwnerSimple(ownerSimple); 
} else { 
    JAXBContext jaxbContextOwner = JAXBContext.newInstance(Owner.class); 
    Unmarshaller jaxbUnmarshallerOwner = jaxbContextOwner.createUnmarshaller(); 
    Owner ownerComplex = (Owner) jaxbUnmarshallerOwner.unmarshal((Node)response.getOwner()); 
    response.setOwnerComplex(ownerComplex); 
} 

//Marshaller to system.out. Your object is well mapped in both cases 
Marshaller marshaller = jaxbContext.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(rx, System.out); 
+0

Эй, там! Это решение отлично звучит. Мне нужно только улучшить одно. Можно ли сопоставить «ownerSimple» с тегом «владелец», когда я создаю вывод, поэтому выходной XML выглядит так же, как входной XML? – inf3ction

+1

Hi @ inf3ction. Тег «ownerSimple» не отображается. Если вы выполните маркер с предоставленным примером кода, он будет писать в теге «владелец» то же содержимое, что и вход в обоих случаях (я проверил его). Чтобы предоставить новый контент, я думаю, вы можете установить в marshall время значение «owner» для ownerSimple или ownerComplex таким же образом, что и unmarshalling. Вероятно, вам нужно будет инициализировать 'JAXBContext' с Owner.class в зависимости от того, используете ли вы простой или сложный объект – pedrofb

+0

, спасибо за решение! – inf3ction

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