Unmarshal NullPointerException(带有 JAXB 参考实现)

Posted

技术标签:

【中文标题】Unmarshal NullPointerException(带有 JAXB 参考实现)【英文标题】:Unmarshal NullPointerException (with JAXB reference implementation) 【发布时间】:2014-04-09 04:20:53 【问题描述】:

我正在尝试解组 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。

【问题讨论】:

【参考方案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 变量的原因是空的。

【讨论】:

Aditya,ClassLoader 类没有静态方法 loadClass :-( 我使用 Java 7. 检查你是否使用了java.lang.ClassLoader,因为java7中的ClassLoader有loadClass方法。检查此链接,docs.oracle.com/javase/7/docs/api/java/lang/… 是的,有,但是这个方法不是静态的。 您可以使用 Class.forName 或参考此答案以使用 loadClass 方法加载您的类,***.com/a/18679222/2968614 classLoader 找到类,所以 clazz 变量不为空。是的,我通过这种方式得到这个类加载器:classLoader = Thread.currentThread().getContextClassLoader();【参考方案2】:

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

基本上,在适配器的“解组”方法中,我通过剥离其值并仅保留其属性来构建一个假“标签”。然后,为了正确提取属性,我使用了 jaxb 解组。

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

【讨论】:

【参考方案3】:

这是 JDK 1.7 中包含的 JAXB (2.2.4-2) 版本中的一个错误。

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

【讨论】:

以上是关于Unmarshal NullPointerException(带有 JAXB 参考实现)的主要内容,如果未能解决你的问题,请参考以下文章

亲測,Eclipse报&quot;An error has occurred,See error log for more details. java.lang.NullPointerExce

亲測,Eclipse报&quot;An error has occurred,See error log for more details. java.lang.NullPointerExce

json 解析:marshal 和 unmarshal

[系列] Go - json.Unmarshal 遇到的小坑

Unmarshal中的动态类型

json.Unmarshal 返回空白结构