5

假设我有一个描述根元素类的模式,其中Root包含一个类具有必需字段名称的位置。List<Entry>Entry

下面是它在代码中的样子:

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();
}

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;
}

如果我提供以下 XML 进行解组:

<root>
  <entry>
    <name>ekeren</name>
  </entry>
  <entry>
  </entry>
</root>

我有一个问题,因为第二个条目不包含名称。所以 unmarshall 产生null.

有没有办法自定义 JAXB 来解组一个Root只包含“好”条目的对象?

4

1 回答 1

5

您可以添加魔术 afterUnmarshal 方法来处理空条目:

@XmlRootElement 
class Root{
  @XmlElement(name="entry")
  public List<Entry> entries = Lists.newArrayList();

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    Iterator<Entry> iter = entries.iterator();
    while (iter.hasNext()) {
      if (iter.next().name == null) iter.remove();
    }
  }
}

编辑:

不确定这是否更适合您,但也许它会有所帮助。您也可以使用 Pacher,例如,如果不是所有需要修复/验证结果的对象都在 afterUnmarshal(..)

在所有解析完成后由 UnmarshallingContext 运行。主要用于解析转发 IDREF,但它可以运行任何操作。(javadoc)

这是一个例子:

@XmlRootElement 
class Entry{
  @XmlElement(name="name",required=true)
  public String name;

  private boolean isValidEntry() {
    return name != null;
  }

  void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
    if (!isValidEntry()) {
      // entry not yet added to parent - use a patcher
      UnmarshallingContext.getInstance().addPatcher(new Patcher() {
        public void run() throws SAXException {
          ((Root)parent).removeEntry(this);
        }
      });
    }
  }
}

不过,我不会过多地滥用它,不仅因为它是仅限 Sun 的 API。

但是,如果您真的在研究不是编组对象本身代码的一部分的可配置的东西。最好在解组后查看某些内容。我想知道Bean Validation (JSR 303)是否不适合您,例如使用Hibernate Validator(不要被名称吓倒,您不需要 Hibernate ORM 来使用它)。我自己没有使用过它,但是使用(新)标准进行验证听起来很合理,不是吗?

于 2010-05-04T15:18:09.407 回答