我遇到的情况是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();
}
在smallBox
@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
仍然存在且不会使用{{ 1}}我已指定名称。
有没有办法强制JAXB(任何实现)将标记设置为子类中指定的名称而不是泛型类型属性?
更新 选定的答案提供了解决方案,但我也想跟进问题。我的问题是双重的:
small-box
课程上使用了@XmlTransient
,而是需要在Payload<T>
方法上使用@XmlAnyElement
注释(尽管我怀疑它并不重要只要只有一个具有注释,就会注释setter / getter对的哪个方法。setPayload(T payload)
,这是一个不完整的JAXB实现,它忽略了用作JacksonJaxbXmlProvider
- 注释属性值的@XmlRootElement
元素。 更改我的JAXB提供程序以使用Java 6/7内置JAXB提供程序生成了我期望的输出。
答案 0 :(得分:2)
您的Payload
类期望任何bean类型作为属性,因此JAXB不知道如何编组该特定对象(在本例中为SmallBox
)。由于您需要在Payload中保留通用属性,因此解决方案应该是
@XmlTransient
注释以使这些类型可用于编组(我想知道它如何与您提到的注释一起使用)setPayload
在Payload
课程中注释@XmlAnyElement
,如下所示公共课Payload { 私人有效载荷;
public T getPayload() {
return payload;
}
@XmlAnyElement
public void setPayload(T payload) {
this.payload = payload;
}
}
@XmlAnyElement
javadoc说
将JavaBean属性映射到XML信息集表示和/或JAXB 元件。
这意味着传递到@XmlRootElement
()的任何已知bean类型(注释为setPayload
)将由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>
希望能帮助你。