[英]How to different objects into the same list using @XmlElements?
我想使用jackson
xml映射器將以下xml(我必須控制並從Web服務獲取)映射到Java bean:
<foo>
<first><val>some</val></first>
<first><val>somemore</val></first>
<second><testval>test</testval></second>
</foo>
我提供的架構是:
<xs:schema>
<xs:include schemaLocation="firstType.xsd"/>
<xs:include schemaLocation="secondType.xsd"/>
<xs:element name="foo">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element ref="first" minOccurs="0"/>
<xs:element ref="second" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
使用xsdtojava
,將生成以下bean:
@XmlRootElement(name = "foo")
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlTest {
@XmlElements({
@XmlElement(name = "first", type = FirstType.class),
@XmlElement(name = "second", type = SecondType.class)
})
@JsonSubTypes({
@JsonSubTypes.Type(name = "first", value = FirstType.class),
@JsonSubTypes.Type(name = "second" , value = SecondType.class)
})
private List<IType> items;
//grouping interface
interface IType {
}
@XmlRootElement(name = "first")
@XmlAccessorType(XmlAccessType.FIELD)
class FirstType implements IType {
private String val;
}
@XmlRootElement(name = "second")
@XmlAccessorType(XmlAccessType.FIELD)
class SecondType implements IType {
private String testval;
}
}
但是我的測試無法轉換xml!
public static void main(String[] args) throws Exception {
String xml =
"<foo>" +
"<first><val>some</val></first>" +
"<second><testval>test</testval></second>" +
"</foo>";
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
ObjectMapper mapper = builder
.modules(new JaxbAnnotationModule(), new JacksonXmlModule())
.defaultUseWrapper(false)
.createXmlMapper(true)
.build();
XmlTest unmarshal = mapper.readValue(xml, XmlTest.class);
System.out.println(unmarshal.items); //prints 'null'
}
項目的結果列表始終為null
,但是為什么呢? 我嘗試了@XmlElements
和@JsonSubTypes
,但是都沒有用。
我做了一個新的測試:
XSD :(像您一樣)
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/test" xmlns:tns="http://www.example.org/test" elementFormDefault="qualified">
<element name="foo">
<complexType>
<sequence maxOccurs="unbounded">
<element name="first" type="tns:FirstType"
maxOccurs="unbounded" minOccurs="0">
</element>
<element name="second" type="tns:SecondType"
maxOccurs="unbounded" minOccurs="0">
</element>
</sequence>
</complexType>
</element>
<complexType name="FirstType">
<sequence>
<element name="val" type="string"></element>
</sequence>
</complexType>
<complexType name="SecondType">
<sequence>
<element name="testval" type="string"></element>
</sequence>
</complexType>
</schema>
xjc插件生成的JAVA:
Foo.class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"firstAndSecond"
})
@XmlRootElement(name = "foo")
public class Foo {
@XmlElements({
@XmlElement(name = "second", type = SecondType.class),
@XmlElement(name = "first", type = FirstType.class)
})
protected List<Object> firstAndSecond;
/**
* Gets the value of the firstAndSecond property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the firstAndSecond property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getFirstAndSecond().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link SecondType }
* {@link FirstType }
*
*
*/
public List<Object> getFirstAndSecond() {
if (firstAndSecond == null) {
firstAndSecond = new ArrayList<Object>();
}
return this.firstAndSecond;
}
public Foo withFirstAndSecond(Object... values) {
if (values!= null) {
for (Object value: values) {
getFirstAndSecond().add(value);
}
}
return this;
}
public Foo withFirstAndSecond(Collection<Object> values) {
if (values!= null) {
getFirstAndSecond().addAll(values);
}
return this;
}
}
FirstType類:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "FirstType", propOrder = {
"val"
})
public class FirstType {
@XmlElement(required = true)
protected String val;
/**
* Gets the value of the val property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getVal() {
return val;
}
/**
* Sets the value of the val property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setVal(String value) {
this.val = value;
}
public FirstType withVal(String value) {
setVal(value);
return this;
}
}
SeconType類:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SecondType", propOrder = {
"testval"
})
public class SecondType {
@XmlElement(required = true)
protected String testval;
/**
* Gets the value of the testval property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getTestval() {
return testval;
}
/**
* Sets the value of the testval property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setTestval(String value) {
this.testval = value;
}
public SecondType withTestval(String value) {
setTestval(value);
return this;
}
}
解組可以在JAXB中完美地工作:
String xml = "<foo>" + "<first><val>some</val></first><second><testval>test</testval></second>" + "</foo>";
Unmarshaller un = JAXBContext.newInstance(Foo.class).createUnmarshaller();
Foo unmarshal = (Foo) un.unmarshal(new StringReader(xml));
System.out.println(unmarshal.getFirstAndSecond());
System.out.println(unmarshal.getFirstAndSecond().size());
但這不適用於Jackson2 ...我在網上做了一些研究,我看到了有關Jackson中有關處理XmlElements注釋的錯誤的討論。
您會看到鏈接https://github.com/FasterXML/jackson-databind/issues/374
解決方案是利用:
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
</dependency>
並在xsdtojava
生成過程中使用-Xsimplify
。
並為該元素顯式定義一個綁定:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
jaxb:extensionBindingPrefixes="xjc simplify"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="xsd/test.xsd">
<jaxb:bindings multiple="true" node="//xs:element[@name='foo']//xs:complexType//xs:sequence">
<simplify:as-element-property/>
</jaxb:bindings>
</jaxb:binding>
</jaxb:bindings>
對於每種類型,這將生成兩個單個元素:
private List<FirstType> firstType;
private List<SecondType> secondType;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.