尝试解组 xml 时出现类转换异常?

发布于 2024-07-16 01:03:33 字数 345 浏览 4 评论 0原文

尝试在此处绕过类转换异常:

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

抛出此异常:

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

我不明白这一点 - 因为该类是由 xjc.bat 工具生成的 - 并且它生成的类我根本没有更改 - 所以应该没有这里的转换问题 - 解组器确实应该给我返回一个可以转换为 FooClass 的类。

关于我做错了什么有什么想法吗?

Trying to get past a class cast exception here:

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

throws this exception:

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

I don't understand this - as the class was generated by the xjc.bat tool - and the classes it generated I have not altered at all - so there should be no casting problems here - the unmarshaller should really be giving me back a class that CAN be cast to FooClass.

Any ideas as to what I am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

予囚 2024-07-23 01:03:33

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

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

这是基于 非官方 JAXB 指南

Does FooClass have the XmlRootElement annotation? If not, try:

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

That's based on the Unofficial JAXB Guide.

巾帼英雄 2024-07-23 01:03:33

在 JAXBElement 上使用 JAXBIntrospector 来获取 schemaObject,如 >>

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

请参阅:JAXB何时unmarshaller.unmarshal返回 JAXBElement; 或者 MySchemaObject?

Use JAXBIntrospector on the JAXBElement to get the schemaObject like >>

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

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

つ低調成傷 2024-07-23 01:03:33

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

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

应该写为

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

或者甚至更好,使其更通用 -

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

I ran into the same problem today, saw the answers here, did some research and looks to me that the most generic solution is to use JAXBIntrospector. Hence -

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

should be written as

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

Or even better, to make it more generic -

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
十年九夏 2024-07-23 01:03:33

有关更完整的解释,请阅读 这篇文章。 事实证明,您的 XSD 必须正确设置,即必须有某个包含所有其他元素的根元素。

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

For a fuller explanation read this article. It turns out that your XSD must be properly set up, i.e. there must be some root element encompassing all the other elements.

XJC does try to put @XmlRootElement annotation on a class that we generate from a complex type. The exact condition is somewhat ugly, but the basic idea is that if we can statically guarantee that a complex type won't be used by multiple different tag names, we put @XmlRootElement.

殤城〤 2024-07-23 01:03:33

我们花了太多时间摆弄 JAXB 工厂类来满足解组器的要求。 我们了解到,使用解组器而不调用 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);
    }

We spent too many hours fidgeting with the JAXB factory class to satisfy the unmarshaller. We've learned that using the unmarshaller without calling the JAXB-generated object factory works alright. Hope the sample code redeems someone's frustration:

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);
    }
听闻余生 2024-07-23 01:03:33

我会查看 XML 文件并确保它大致符合您期望看到的内容。

我还临时将代码更改为:

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

如果第一个失败,则类转换将在 unmarshal 方法内发生,如果成功,那么您可以看到要返回的实际类,然后找出为什么它没有返回你期望它是什么。

I'd look at the XML file and make sure it is roughly what you expect to see.

I'd also temporarily change the code to:

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

If the first one failes then the class cast is happening inside the unmarshal method, if it succeeds then you can see the actual class that you are getting back and then figure out why it isn't what you expect it to be.

生生漫 2024-07-23 01:03:33

基于同事的预览答案,以防万一有人仍在寻找答案。

我遇到的问题是我的方案的根元素被定义为:

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

因此我在以下位置收到了强制转换异常:

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());

这为我解决了问题。

Building on the previews answers from colleagues, just in case anybody is still looking for an answer.

I had the issue of having the root element of my scheme being defined as:

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

And therefore I was getting a Cast Exception at:

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
    }

What I did was to change the first line of the try block to:

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

That resolved the problem for me.

北城孤痞 2024-07-23 01:03:33

您绝对确定 FooClass 是您传递给它的 xml 输入源的根元素吗? Unmarshall 将返回 xjc 创建的根元素的对象。

Are you absolutely sure FooClass is the root element of the xml input source you passed it? Unmarshall will return an object of the root element created by xjc.

你的心境我的脸 2024-07-23 01:03:33

有时,您的 XSD 定义具有多个不同的根元素(例如 WSDL 中定义的 XSD),在这种情况下,生成的类缺少 @XmlRootElement。 因此,正如用户 mbrauh 已经写的那样,您必须获取 JAXBElement 的值。 在我的例子中,我使用:

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

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

Sometimes you have a XSD definition with multiple different root elements (for instance XSD defined in WSDL) and in that case the generated classes are missing @XmlRootElement. So as user mbrauh already wrote you have to get the value of JAXBElement. In my case I used:

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

So using generics you can easily avoid double type casting.

够钟 2024-07-23 01:03:33

如果您有访问权限,则可以修改 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(修改您的根元素“schema”以获得
xs:complexType 位于标记 xs:element) 内:

<?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 将生成根元素!

If you have access and you can modify the XSD.
For me, this issue appends when I generate the XSD from XML with IDEA.

With this xml :

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

IDEA generate an XSD like that and JAXB won't generate an root element :

<?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>

BUT, if you modify the XSD in this way (modify your root element "schema" in order to get the
xs:complexType inside the tag xs:element) :

<?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 will generate the root element !

尝蛊 2024-07-23 01:03:33

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

Specify @XmlRootElement(name="specifyName", namespace="namespace") to transforming object.

陌上芳菲 2024-07-23 01:03:33

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

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

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

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

I also encountered the "Javax.xml.bind.JAXBElement cannot be cast to" error and found this very simple solution:

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

Since, apparently, an object of type JAXBElement is returned, you need to typecast its value instead.

Source: https://forums.oracle.com/thread/1625944

绻影浮沉 2024-07-23 01:03:33

尝试这个:

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

Try this:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;
月牙弯弯 2024-07-23 01:03:33

就我而言,当尝试从 SOAPUI 应用程序发送肥皂请愿书时,我收到错误。 我需要将属性“剥离空格”设置为 true 以跳过此错误。

调试收到的内容时,会出现一个包含以下内容的列表:

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

希望对某人有所帮助。

In my case, I get the error when trying to send a soap petition from the SOAPUI application. I need to set the property 'strip whitespaces' to true to skip this error.

When debug the content received, is a list with the next content:

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

Hope help someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文