2015-02-18 3 views
1

Я пытаюсь создать простой образец клиента для службы REST. Сервер может отправлять ответ как в XML, так и в JSON. Я не могу изменить поведение сервера.JAXB сопоставление XML-документа с Java-объектом

Я сделал заявление о своей стихии:

<xsd:complexType name="ServerInformation"> 
    <xsd:sequence> 
     <xsd:element name="type" type="xsd:string"/> 
     <xsd:element name="name" type="xsd:string" /> 
     <xsd:element name="version" type="xsd:string" /> 
     <xsd:element name="zone" type="xsd:string" /> 
     <xsd:element name="date" type="xsd:dateTime" /> 
     <xsd:element name="timeout" type="xsd:int" /> 
    </xsd:sequence> 
</xsd:complexType> 

У меня есть проблема только в поле «тип». Когда сервер отвечает с ответом JSON, у меня есть «тип»: узел «server_information». Таким образом, отображение корректно преобразуется в Java. Я могу вызвать метод foo.getType(), и он возвращает «server_information». Это ожидаемое поведение.

Я хочу сделать то же самое, когда сервер ответит с ответом XML. Проблема в том, что у меня нет узла с именем «type». значение типа содержится в корневом узле ответа XML. Здесь XML ответ:

<server_information> 
     <name>Server Name</name> 
     <version>[development build]</version> 
     <zone>Europe/Paris</zone> 
     <date>2015-02-18T16:15:35.892Z</date> 
     <timeout>300</timeout> 
</server_information> 

У меня нет каких-либо проблем с отображением остальных элементов (название, версия, зона ...). Только с типом.

Итак, мой вопрос в том, как я могу указать JAXB для получения имени корневого узла («server_information») в элемент «type»? Я думаю, что это должно быть сделано с обязательным файлом (serverInformation.xjb), но я не знаю, как это сделать ...

Мне также нужно быть совместимым как с JSON, так и с XML. Поэтому в JSON я все еще могу использовать узел типа.

+0

Вы пытаетесь использовать объекты тот же JAXB для XML и JSON? – artbristol

+0

Я могу использовать отдельные файлы для описания WADL, если это необходимо, но в Java я хочу только один объект со всеми полями. Объект JSON уже корректен, я должен иметь возможность получить корневое имя XML-файла и поместить его в поле «type». – hiveship

+0

Если честно, я не думаю, что это стоит усилий. Я бы выбрал JSON или XML и придерживаюсь этого. Если вы делаете образец клиента *, просто создайте один из двух типов. Отвечает ли сервер заголовку 'Accept: '? – artbristol

ответ

0

Я решил свою проблему, удалив поле «type» в моем xsd-файле и добавив аннотацию Java, содержащую корневой элемент XML.

Теперь я могу получить тип, используя значение этой аннотации. Все мои объекты расширяют абстрактный класс с помощью метода getType().

@XmlRootElement(name = "server_information") 
public class ServerInformation extends AbstractEntityBase 
{...} 

Абстрактный класс для каждого объекта:

public abstract class AbstractEntityBase{ 

public final String getType(){ 
    return getClass().getAnnotation(XmlRootElement.class).name(); 
} 

}

XSD файл:

<xsd:complexType name="server_information"> 
    <xsd:sequence> 
     <xsd:element name="version" type="xsd:string" /> 
     <.../> 
    </xsd:sequence> 
</xsd:complexType> 

XSD привязок файла:

<jaxb:bindings schemaLocation="ServerInformation.xsd" node="/xsd:schema/xsd:complexType[1]"> 

    <annox:annotate target="class"> 
     @javax.xml.bind.annotation.XmlRootElement(name = "server_information") 
    </annox:annotate> 

    <annox:annotate target="class"> 
     @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true, value = {"type"}) 
    </annox:annotate> 

    <jaxb:globalBindings> 
     <xjc:superClass name="com.foo.AbstractEntityBase" /> 
    </jaxb:globalBindings> 
</jaxb:bindings>