JAXB覆盖@XmlElement类型的列表 [英] JAXB override @XmlElement type of list

查看:286
本文介绍了JAXB覆盖@XmlElement类型的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个简单的类 Bean1 ,其子列表类型为 BeanChild1

There's a simple class Bean1 with a sublist of type 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 { ... }

我试图覆盖该类,以更改列表的类型。
新的子类(即 BeanChild2 )扩展了前一个(即 BeanChild1 )。

I am trying to override the class, to change the type of the list. The new child-class (i.e. BeanChild2) extends the previous one (i.e. 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
}

测试显示此列表仍包含<$的子项c $ c> BeanChild1 。

The test reveals that that this list still contains childs of BeanChild1.

那么,如何强制它填充 childList 字段 BeanChild2 实例?

So, how can I force it to populate the childList field with BeanChild2 instances ?

如果没有简单的解决方案,那么随意发布更具创意的解决方案(例如使用 XmlAdapter s, Unmarshaller.Listener ,也许是父母的额外注释或儿童班......)

If there are no easy solutions, then feel free to post more creative solutions (e.g. using XmlAdapters, Unmarshaller.Listener, perhaps an additional annotation on the parent or child class ...)

推荐答案

无法改变(例如覆盖) @ XmlElement 超类的注释。至少不使用注释。

There is no way to change (e.g. override) the @XmlElement annotation of a super class. At least not using annotations.


  • 你使用的 @XmlAccessorType 并不重要(例如 FIELD PROPERTY PUBLIC NONE )。

  • 如果将注释放在字段或getter上,则没有任何区别。

  • It doesn't matter what @XmlAccessorType you use (e.g. FIELD, PROPERTY, PUBLIC, NONE).
  • It doesn't make any difference if you put the annotations on the fields or on the getters.

然而,有一个合理的选择。 JAXB的MOXy实现提供了在xml文件中定义元数据/绑定的能力。事实上,每个java注释都有一个XML替代方案。但它会变得更好:你可以将java注释和这些xml元数据结合起来。很酷的是,MOXy会合并两个声明,如果发生冲突, XML定义的元数据会得到一个优先级较高。

However, there is a reasonable alternative. The MOXy implementation of JAXB offers the ability to define the metadata/bindings in an xml file. In fact every java annotation has an XML alternative. But it gets better: You can combine both java annotations AND these xml metadata. The cool thing, is that MOXy will merge both declarations, and in case of conflict, the XML defined metadata gets a higher priority.

假设 Bean1 类如上所示进行注释。然后可以在xml文件中重新定义绑定。例如:

Assuming that the Bean1 class is annotated as above. Then it's possible to redefine the binding, in an xml file. e.g.:

<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将合并java注释和XML绑定,如果发生冲突,则会定义XML定义的设置适用。在这种情况下,早期的 @XmlElement(name = child)注释被xml定义替换,该定义等同于 @XmlElement(name = child, type = BeanChild2.class)

MOXy will merge the java annotations and the XML bindings, and in case of a conflict the XML defined settings are applied. 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).

您可以阅读有关XML绑定的更多信息这里

You can read more about the XML bindings here.

这篇关于JAXB覆盖@XmlElement类型的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆