JAXB编组/解组NullpointerException两难

Fri*_*rdt 5 java xml jaxb

我正在使用一个带java.xml.bind注释的Bean来创建一个XML输出格式,如果它们是空的,则会省略它们.为此目的,相应的Getter必须如下所示:

@XmlElementWrapper(name = "titles")
@XmlElement(name = "title")
public List<XmlTitle> getTitles() {
    if (titles.size() == 0) {
        return null;
    }
    return titles;
}
Run Code Online (Sandbox Code Playgroud)

这在编组期间工作正常.可悲的是,我NullpointerException想要解析同一个XML文件:

java.lang.NullPointerException
    at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:305)
    at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:269)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:121)
    at com.sun.xml.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:213)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:538)
    at com.sun.xml.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.endElement(ValidatingUnmarshaller.java:107)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:158)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2973)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:258)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:229)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.unmarshal(Jaxb2Marshaller.java:754)
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.unmarshal(Jaxb2Marshaller.java:735)
Run Code Online (Sandbox Code Playgroud)

这与Getter返回有关null.正如一些JAXB专家在Glassfish JAXB论坛上解释的那样:

JAXB unmarshaller不期望set类型属性的setter; 它只是使用x.getSomeList().add(y)来添加另一个子节点.

我如何才能最好地解决这个难题?

Rad*_*nta 0

您可以通过实现 JAXB 定义的回调来解决它。使用 unmarshaller 回调 afterUnmarshal 来清理列表。

@XmlElement (name = "title")
List<XmlTitle> theTitles = new ArrayList<XmlTitle>();  
...
void afterUnmarshal(Unmarshaller aUnmarshaller, Object aParent)
{
    if (requiredBooks != null)
    {
        Iterator<XmlTitle> iterator = theTitles.iterator();
        while (iterator.hasNext())
        {
            XmlTitle theTitle = iterator.next();
            if (null == theTitle)
            {                    
                iterator.remove();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)