Unmarshal NullPointerException(使用JAXB参考实现)

时间:2014-03-06 13:31:55

标签: java xml nullpointerexception jaxb

我正在尝试解组xml文件,但是从JAXB库的深处得到非常奇怪的NPE。请你帮我解决这个问题吗?

这是异常堆栈跟踪的顶部:

java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.handleGenericException(Loader.java:245)
at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:123)
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)

这是xml类代码:

public class Base {
    public Base() {
    }
}

public class A  extends Base {
    public A() {
    }
}

public class B extends Base{
    public B() {
    }
}


@XmlRootElement(name = "test")
@XmlAccessorType
public class TestXml {
    @XmlElementWrapper(name = "list")
    @XmlAnyElement
    @XmlJavaTypeAdapter(Adapter.class)
    public List<Base> list = new ArrayList<>();
}

这是适配器的unmarshal()方法,它取自here并略有修改。

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public T unmarshal(Element element) throws Exception {
    if (null == element) {
        return null;
    }

    // 1. Determine the values type from the type attribute.
    Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));

    // 2. Unmarshal the element based on the value's type.
    DOMSource source = new DOMSource(element);
    Unmarshaller unmarshaller = getJAXBContext(clazz).createUnmarshaller();
    JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);

    return (T) jaxbElement.getValue();      
}

这是测试代码:

JAXBContext jaxbContext = JAXBContext.newInstance(TestXml.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();       

TestXml auth = (TestXml) unmarshaller.unmarshal(new File("testData/test.xml"));

最后,这是我试图解组的xml文件:

<test>
    <list>
        <item class="my.package.A" />
        <item class="my.package.B" />
    </list>
</test>

在调试时我发现适配器工作正常,即unmarshall()方法总是返回正确类的实例,但在它之后发生了一些不好的事情。

我发现的下一件事是适配器的代码

JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);

导致NPE。当我删除这行代码并将unmarshall()的return语句替换为

return new A(); //for example

没有发生NPE。

3 个答案:

答案 0 :(得分:1)

尝试更改此行,

// 1. Determine the values type from the type attribute.
    Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));

要,

// 1. Determine the values type from the type attribute.
    Class<?> clazz = ClassLoader.loadClass(element.getAttribute("class"));

你的clazz变量的原因是null。

答案 1 :(得分:1)

在另一个解组过程中尝试处理解组过程时,我有完全相同的堆栈跟踪。

基本上,在&#39; unmarshal&#39;一个适应器的方法,我建立了一个假的标签&#39;通过剥离其价值并仅保留其属性。然后,为了正确提取属性,我使用了jaxb unmarshalling。

jaxb中的错误很深,我的代码中没有发现任何错误。我通过迁移到最新版本解决了我的问题。最好的jaxb-core库,从2.2.6到2.2.11。

答案 2 :(得分:0)

这是JDK 1.7附带的JAXB(2.2.4-2)版本中的错误。

对我来说,在类路径中包括最新版本的JAXB(2.2.11)解决了这个问题。