[英]How do I specify the name of a JAXB element using Java generics?
我遇到一種情況,其中Java對象包含需要將其編組為xml的通用Payload<T>
。 因此,給出以下類:
AbstractBox
@XmlTransient
public abstract class AbstractBox {
String type = this.getClass().getSimpleName();
String name = this.getClass().getCanonicalName();
// setters/getters snipped
public abstract String saySomething();
}
小盒子
@XmlRootElement(name="small-box")
@XmlType(name="small-box")
public class SmallBox extends AbstractBox {
@XmlElement
public String getMsg() {
return saySomething();
}
public void setMsg(String msg) {
// do nothing
}
@Override
public String saySomething() {
return "I'm a small box";
}
}
有效載荷
@XmlTransient
public class Payload<T> {
private T payload;
public T getPayload() {
return payload;
}
public void setPayload(T payload) {
this.payload = payload;
}
}
和一些這樣的代碼:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbAnnotationsTest<P>
{
String name;
int age;
int id;
Payload<P> payload;
// setters and getters snipped
public static void main(String[] args) {
JaxbAnnotationsTest<AbstractBox> example = new JaxbAnnotationsTest<AbstractBox>();
example.setName("Brion");
example.setId(100);
example.setAge(34);
Payload<AbstractBox> object = new Payload<AbstractBox>();
object.setPayload(new SmallBox());
example.setPayloadContainer(object);
try {
XmlMapper xmapper = new XmlMapper();
xmapper.writeValue(System.out, example);
} catch (Exception ex) {
System.err.println("Damn..." + ex.getMessage());
}
}
我希望看到:
<JaxbAnnotationsTest>
<name>Brion</name>
<age>34</age>
<id>100</id>
<payloadContainer>
<small-box>
<type>SmallBox</type>
<name>sandbox.xml.jaxb.annotations.SmallBox</name>
<msg>I'm a small box</msg>
</small-box>
</payloadContainer>
</JaxbAnnotationsTest>
但是我得到了:
<JaxbAnnotationsTest>
<name>Brion</name>
<age>34</age>
<id>100</id>
<payloadContainer>
<payload>
<type>SmallBox</type>
<name>sandbox.xml.jaxb.annotations.SmallBox</name>
<msg>I'm a small box</msg>
</payload>
</payloadContainer>
</JaxbAnnotationsTest>
我嘗試在具體的子類上使用@XmlType
將payload
更改為small-box
但這也不起作用。 如果刪除Payload<P>
對象並僅具有通用類型P的類成員payload
,則paymentContainer
標記將消失,但是payload
仍然存在,並且不使用我指定的small-box
名稱。
有沒有一種方法可以強制JAXB(任何實現)將標記設置為子類中指定的名稱,而不是通用類型屬性?
更新:選定的答案提供了解決方案,但我也想跟進該問題。 我的問題有兩個:
Payload<T>
類上使用@XmlTransient
,並且需要在setPayload(T payload)
方法上使用@XmlAnyElement
批注(盡管我懷疑只要對setter / getter對的哪個方法都進行了注釋就可以了因為只有一個具有注釋)。 JacksonJaxbXmlProvider
這是一個不完整的JAXB實現這是忽略@XmlRootElement
用作的值的元素的@XmlAnyElement
-annotated屬性。 更改我的JAXB提供程序以使用Java 6/7內置JAXB提供程序會生成預期的輸出。
您的Payload
類希望將任何bean類型都作為屬性,因此JAXB不知道如何編組該特定對象(在本例中為SmallBox
)。 由於您需要將通用屬性保留在有效負載中,因此解決方案應為
@XmlTransient
批注以使這些類型可用於編組(我想知道它如何與您提到的此批注一起使用) setPayload
在Payload
類@XmlAnyElement
如下 公共類有效載荷{私有T有效載荷;
public T getPayload() {
return payload;
}
@XmlAnyElement
public void setPayload(T payload) {
this.payload = payload;
}
}
@XmlAnyElement
javadoc說
將JavaBean屬性映射到XML信息集表示形式和/或JAXB元素。
這意味着傳遞給setPayload
()的任何已知bean類型(用@XmlRootElement
注釋)將由JAXB解析為其對應的類型,這里bean是SmallBox
,否則為默認元素類型(我認為應該是默認元素類型) org.w3c.dom.Element
實現)。 進行此更改后,它將很好地將JaxbAnnotationsTest
編組為以下xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbAnnotationsTest>
<age>34</age>
<id>100</id>
<name>Brion</name>
<payloadContainer>
<small-box>
<name>org.mycode.SmallBox</name>
<type>SmallBox</type>
<msg>I'm a small box</msg>
</small-box>
</payloadContainer>
</jaxbAnnotationsTest>
希望對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.