Java 尝试解组 xml 时出现 Class Cast Exception?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/707084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:34:37  来源:igfitidea点击:

Class Cast Exception when trying to unmarshall xml?

javajaxbjaxb2

提问by Vidar

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.

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

Any ideas as to what I am doing wrong?

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

采纳答案by Jon Skeet

Does FooClasshave the XmlRootElementannotation? If not, try:

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

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.

这是基于Unofficial JAXB Guide

回答by Greg Noe

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.

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

回答by TofuBeer

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

我会查看 XML 文件并确保它大致符合您的预期。

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.

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

回答by Vidar

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.

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

XJC does try to put @XmlRootElementannotation 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.

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

回答by MAbraham1

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

我们花了太多时间来处理 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);
    }

回答by user752749

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

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

回答by Alberto A. Medina

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:

因此,我在以下位置收到了 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
    }

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

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

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

That resolved the problem for me.

那为我解决了问题。

回答by Rahul Thakur

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

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

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?

参考:JAXB unmarshaller.unmarshal 何时返回 JAXBElement<MySchemaObject> 或 MySchemaObject?

回答by mbrauh

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

我还遇到了“Javax.xml.bind.JAXBElement cannot be cast to”错误,发现了这个非常简单的解决方案:

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.

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

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

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

回答by Marek Branicky

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:

有时,您的 XSD 定义包含多个不同的根元素(例如在 WSDL 中定义的 XSD),在这种情况下,生成的类缺少 @XmlRootElement。因此,由于用户 mbrauh 已经写过,您必须获取 JAXBElement 的值。就我而言,我使用了:

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

So using generics you can easily avoid double type casting.

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