尝试解组xml时的类强制转换异常?

时间:2009-04-01 19:57:11

标签: java jaxb jaxb2

尝试通过此处的类型转换异常:

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

抛出此异常:

java.lang.ClassCastException: javax.xml.bind.JAXBElement

我不明白这一点 - 因为这个类是由xjc.bat工具生成的 - 它生成的类我根本没有改变 - 所以这里应该没有施法问题 - unmarshaller应该真的给我了支持一个可以投射到FooClass的类。

关于我做错了什么的想法?

14 个答案:

答案 0 :(得分:103)

FooClass是否有XmlRootElement注释?如果没有,请尝试:

Source source = new StreamSource(inputStream);
JAXBElement<FooClass> root = unmarshaller.unmarshal(source, FooClass.class);
FooClass foo = root.getValue();

这是基于Unofficial JAXB Guide

答案 1 :(得分:15)

在JAXBElement上使用JAXBIntrospector来获取类似&gt;&gt;

的schemaObject
JAXBContext jaxbContext = JAXBContext.newInstance(Class.forName(className));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object schemaObject = JAXBIntrospector.getValue(unmarshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())));

参考:when does JAXB unmarshaller.unmarshal returns a JAXBElement<MySchemaObject> or a MySchemaObject?

答案 2 :(得分:14)

我今天遇到了同样的问题,在这里看到了答案,做了一些研究,并向我看,最通用的解决方案是使用 JAXBIntrospector 。因此 -

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

应该写成

FooClass fooClass = (FooClass) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));

甚至更好,使它更通用 -

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));

答案 3 :(得分:9)

如需更全面的解释,请阅读this article。事实证明你的XSD必须正确设置,即必须有一些根元素包含所有其他元素。

  

XJC确实尝试将@XmlRootElement注释放在我们从复杂类型生成的类上。确切的条件有点难看,但基本的想法是,如果我们可以静态地保证复杂类型不会被多个不同的标签名称使用,我们就放@XmlRootElement

答案 4 :(得分:3)

我会查看XML文件并确保它大致与您期望的相同。

我还会暂时将代码更改为:

Object o = unmarshaller.unmarshal(inputStream);
System.out.println(o.getClass());

如果第一个失败然后在unmarshal方法中发生了类强制转换,如果它成功,那么你可以看到你正在返回的实际类,然后弄清楚为什么它不是你期望的那样。

答案 5 :(得分:3)

我们花了太多时间来安装JAXB工厂类来满足unmarshaller。我们已经了解到使用unmarshaller 而不用调用JAXB生成的对象工厂可以正常工作。希望示例代码能够挽回某人的挫败感:

System.out.println("Processing generic-type unmarshaller: ");
MessageClass mcObject = unmarshalXml(MessageClass.class, msgQryStreamSource,
    NAMESPACE + "." + "MessageClass");

public static <T> T unmarshalXml(Class<T> clazz, StreamSource queryResults,
    String contextNamespace)
    {
        T resultObject = null;
        try {
            //Create instance of the JAXBContext from the class-name
            JAXBContext jc;
            jc = JAXBContext.newInstance(Class.forName(clazz.getName()));
            Unmarshaller u = jc.createUnmarshaller();
            resultObject = clazz.cast(u.unmarshal(queryResults));
            }
              //Put your own error-handling here.
        catch(JAXBException e)
        {
            e.printStackTrace();
        }
        catch (ClassCastException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        return clazz.cast(resultObject);
    }

答案 6 :(得分:2)

根据同事的预览答案,以防任何人仍在寻找答案。

我遇到了将我的方案的根元素定义为:

的问题
<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

因此我得到了一个Cast Exception:

try {            
        javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getPackage().getName());            
        javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
        File f = FileUtil.toFile(this.getPrimaryFile());            
        mobilityConfigType = (MobilityModelConfigType)unmarshaller.unmarshal(FileUtil.toFile(this.getPrimaryFile()));
    } catch (javax.xml.bind.JAXBException ex) {            
        java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
    }

我所做的是将try块的第一行更改为:

javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getName());

这解决了我的问题。

答案 7 :(得分:1)

你绝对相信FooClass是你传递的xml输入源的根元素吗? Unmarshall将返回由xjc创建的根元素的对象。

答案 8 :(得分:1)

有时你有一个带有多个不同根元素的XSD定义(例如在WSDL中定义的XSD),在这种情况下,生成的类缺少@XmlRootElement。因此,正如用户mbrauh已经写过的那样,你必须得到JAXBElement的值。就我而言,我用过:

FooClass request = ((JAXBElement< FooClass >) marshaller.unmarshal(new StreamSource(classPathResource.getInputStream()))).getValue();

因此,使用泛型可以轻松避免双重类型转换。

答案 9 :(得分:0)

指定@XmlRootElement(name =“specifyName”,namespace =“namespace”)来转换对象。

答案 10 :(得分:0)

我还遇到了“Javax.xml.bind.JAXBElement无法转换为”错误,发现这个非常简单的解决方案:

FooClass fooClass = (FooClass) ((JAXBElement) u.unmarshal(new File("xml/foo.xml")) ).getValue();

由于显然返回了JAXBElement类型的对象,因此需要对其值进行类型转换。

来源:https://forums.oracle.com/thread/1625944

答案 11 :(得分:0)

试试这个:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;

答案 12 :(得分:0)

在我的情况下,尝试从SOAPUI应用程序发送肥皂请求时出现错误。我需要将“ strip whitespaces”属性设置为true才能跳过此错误。

当调试收到的内容时,是包含下一个内容的列表:

[0] = "\n"
[1] = JAXBElement
[2] = "\n"

希望可以帮助某人。

答案 13 :(得分:0)

如果具有访问权限,则可以修改XSD。 对我来说,当我使用IDEA从XML生成XSD时,这个问题会出现。

使用此xml:

<?xml version="1.0"?>
<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

IDEA会生成类似的XSD,而JAXB不会生成根元素:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="schema" type="schemaType"/>
  <xs:complexType name="schemaType">
    <xs:sequence>
      <xs:element type="elementType" name="element"/>
      <xs:element type="complexTypeType" name="complexType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="elementType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
        <xs:attribute type="xs:string" name="type"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="complexTypeType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

但是,如果您以这种方式修改XSD(请修改您的根元素“模式”以获取 标记xs:element内的xs:complexType):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="schema">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="elementType" name="element"/>
        <xs:element type="complexTypeType" name="complexType"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="schemaType">
    <xs:sequence>
      <xs:element type="elementType" name="element"/>
      <xs:element type="complexTypeType" name="complexType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="elementType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
        <xs:attribute type="xs:string" name="type"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="complexTypeType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

JAXB将生成根元素!