[英]JAXB override @XmlElement type of list
There's a simple class Bean1
with a sublist of type BeanChild1
. 有一个简单的
Bean1
类,其子列表类型为BeanChild1
。
@XmlRootElement(name="bean")
@XmlAccessorType(XmlAccessType.PROPERTY)
public static class Bean1
{
public Bean1()
{
super();
}
private List<BeanChild1> childList = new ArrayList<>();
@XmlElement(name="child")
public List<BeanChild1> getChildList()
{
return childList;
}
public void setChildList(List<BeanChild1> pChildList)
{
childList = pChildList;
}
}
public static class BeanChild1 { ... }
I am trying to override the class, to change the type of the list. 我试图覆盖该类,以更改列表的类型。 The new child-class (ie
BeanChild2
) extends the previous one (ie BeanChild1
) . 新的子类(即
BeanChild2
)扩展了前一个子类(即BeanChild1
)。
public static class Bean2 extends Bean1
{
public Bean2()
{
super();
}
@Override
@XmlElement(name="child", type=BeanChild2.class)
public List<BeanChild1> getChildList()
{
return super.getChildList();
}
}
public static class BeanChild2 extends BeanChild1 { }
So, here is how I tested it: 因此,这是我如何测试它:
public static void main(String[] args)
{
String xml = "<bean>" +
" <child></child>" +
" <child></child>" +
" <child></child>" +
"</bean>";
Reader reader = new StringReader(xml);
Bean2 b2 = JAXB.unmarshal(reader, Bean2.class);
assert b2.getChildList().get(0) instanceof BeanChild2; // fails
}
The test reveals that that this list still contains childs of BeanChild1
. 测试表明该列表仍包含
BeanChild1
。
So, how can I force it to populate the childList
field with BeanChild2
instances ? 因此,如何强制它使用
BeanChild2
实例填充childList
字段?
If there are no easy solutions, then feel free to post more creative solutions (eg using XmlAdapter
s, Unmarshaller.Listener
, perhaps an additional annotation on the parent or child class ...) 如果没有简单的解决方案,请随时发布更多有创意的解决方案(例如,使用
XmlAdapter
, Unmarshaller.Listener
,可能在父类或子类上附加注释...)
There is no way to change (eg override) the @XmlElement
annotation of a super class. 无法更改(例如,重写)超类的
@XmlElement
注释。 At least not using annotations. 至少不使用注释。
@XmlAccessorType
you use (eg FIELD
, PROPERTY
, PUBLIC
, NONE
). @XmlAccessorType
都没有关系(例如FIELD
, PROPERTY
, PUBLIC
, NONE
)。 However, there is a reasonable alternative. 但是,有一个合理的选择。 The MOXy implementation of JAXB offers the ability to define the metadata/bindings in an xml file .
JAXB的MOXy实现提供了在xml文件中定义元数据/绑定的功能 。 In fact every java annotation has an XML alternative.
实际上,每个Java注释都有XML替代项。 But it gets better: You can combine both java annotations AND these xml metadata.
但它会变得更好: 您可以将Java注释和这些xml元数据结合在一起。 The cool thing, is that MOXy will merge both declarations, and in case of conflict, the XML defined metadata gets a higher priority.
很棒的事情是,MOXy将合并两个声明,并且在发生冲突的情况下, XML定义的元数据将具有更高的优先级。
Assuming that the Bean1
class is annotated as above. 假设
Bean1
类如上所述。 Then it's possible to redefine the binding, in an xml file. 然后可以在xml文件中重新定义绑定。 eg:
例如:
<xml-bindings xml-accessor-type="PROPERTY">
<java-types>
<java-type name="Bean1">
<xml-element java-attribute="childList" name="child"
type="BeanChild2" container-type="java.util.ArrayList" />
</java-type>
</java-types>
</xml-bindings>
This new bindings file is needed during the creation of the context object. 创建上下文对象期间需要此新的绑定文件。
// use a map to reference the xml file
Map<String, Object> propertyMap = new HashMap<>();
propertyMap.put(JAXBContextProperties.OXM_METADATA_SOURCE, "bindings.xml");
// pass this properyMap during the creation of the JAXB context.
JAXBContext context = JAXBContext.newInstance(..., propertyMap);
MOXy will merge the java annotations and the XML bindings, and in case of a conflict the XML defined settings are applied. MOXy将合并Java批注和XML绑定,并且在发生冲突的情况下,将应用XML定义的设置。 In this case, the earlier
@XmlElement(name=child)
annotation is replaced by an xml definition which is equivalent to @XmlElement(name=child, type=BeanChild2.class)
. 在这种情况下,较早的
@XmlElement(name=child)
注释将替换为xml定义,该定义等同于@XmlElement(name=child, type=BeanChild2.class)
。
You can read more about the XML bindings here . 您可以在此处阅读有关XML绑定的更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.