假设我有一个描述根元素类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
对象?
答案 0 :(得分:5)
您可以添加magic afterUnmarshal method来处理空条目:
@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-only API。
但是,如果您真的在寻找可配置的东西,而这些东西不是编组对象本身的代码的一部分。解组后最好看一些东西。我想知道Bean Validation (JSR 303)是否不适合你,例如使用Hibernate Validator(不要被名字吓倒,你不需要Hibernate ORM来使用它)。我自己没有使用它,但使用(新)标准进行验证听起来合理,不是吗?