JAXB 映射 XML 文档到 Java 对象
JAXB mapping XML document to Java Object
我正在尝试为 REST 服务制作一个简单的客户端示例。
服务器可以在 XML 和 JSON 中发送响应。我无法更改服务器的行为。
我声明了我的元素:
<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>
我只有 "type" 字段有问题。当服务器回答 JSON 响应时,我有一个 "type" : "server_information" 节点。所以映射正确地做成了Java。我可以调用方法 foo.getType() 并且它 returns "server_information"。这是预期的行为。
当服务器以 [=44=] 响应回答时,我想做同样的事情。问题是我没有名为 "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中,我仍然可以使用"type"节点。
我通过删除 xsd 文件中的 "type" 字段并添加包含 XML 根元素的 Java 注释解决了我的问题。
我现在可以使用此注释的值获取类型。我所有的实体都使用 "getType()" 方法扩展了抽象 class。
@XmlRootElement(name = "server_information")
public class ServerInformation extends AbstractEntityBase
{...}
每个实体的摘要 class:
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>
我正在尝试为 REST 服务制作一个简单的客户端示例。 服务器可以在 XML 和 JSON 中发送响应。我无法更改服务器的行为。
我声明了我的元素:
<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>
我只有 "type" 字段有问题。当服务器回答 JSON 响应时,我有一个 "type" : "server_information" 节点。所以映射正确地做成了Java。我可以调用方法 foo.getType() 并且它 returns "server_information"。这是预期的行为。
当服务器以 [=44=] 响应回答时,我想做同样的事情。问题是我没有名为 "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中,我仍然可以使用"type"节点。
我通过删除 xsd 文件中的 "type" 字段并添加包含 XML 根元素的 Java 注释解决了我的问题。
我现在可以使用此注释的值获取类型。我所有的实体都使用 "getType()" 方法扩展了抽象 class。
@XmlRootElement(name = "server_information")
public class ServerInformation extends AbstractEntityBase
{...}
每个实体的摘要 class:
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>