57

ここでクラスキャスト例外を乗り越えようとしています:

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

この例外をスローします:

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

私はこれを理解していません-クラスはxjc.batツールによって生成されたので-そしてそれが生成したクラスは私がまったく変更していません-したがってここではキャストの問題はないはずです-アンマーシャラーは本当に私にクラスを返すはずですFooClassにキャストできます。

私が間違っていることについて何か考えはありますか?

4

14 に答える 14

124

注釈はFooClassありますか?XmlRootElementそうでない場合は、次を試してください。

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

これは、非公式のJAXBガイドに基づいています。

于 2009-04-01T20:04:11.843 に答える
19

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> または MySchemaObject を返しますか?

于 2012-05-21T06:02:45.900 に答える
17

私は今日同じ問題に遭遇し、ここで答えを見て、いくつかの調査を行い、最も一般的な解決策はJAXBIntrospectorを使用することだと私には見えます。したがって -

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

次のように書く必要があります

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

またはさらに良いことに、より一般的にするために-

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
于 2015-01-10T11:09:44.423 に答える
9

詳細な説明については、この記事をお読みください。XSD を適切に設定する必要があることがわかりました。つまり、他のすべての要素を含むルート要素が必要です。

@XmlRootElementXJC は、複合型から生成したクラスに注釈を付けようとします。正確な条件はやや醜いですが、基本的な考え方は、複雑な型が複数の異なるタグ名で使用されないことを静的に保証できる場合、@XmlRootElement.

于 2009-04-29T16:48:06.353 に答える
4

unmarshaller を満足させるには、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);
    }
于 2011-02-11T15:54:46.670 に答える
3

XML ファイルを調べて、おおむね期待どおりのものであることを確認します。

また、一時的にコードを次のように変更します。

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

最初のメソッドが失敗した場合、アンマーシャル メソッド内でクラス キャストが行われています。成功した場合は、取得している実際のクラスを確認し、それが期待どおりではない理由を理解できます。

于 2009-04-01T23:26:39.330 に答える
2

誰かがまだ答えを探している場合に備えて、同僚からのプレビューの答えに基づいて構築します。

スキームのルート要素が次のように定義されているという問題がありました。

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

それで問題は解決しました。

于 2011-11-02T14:40:05.640 に答える
1

FooClassが渡したxml入力ソースのルート要素であることを絶対に確信していますか?Unmarshallは、xjcによって作成されたルート要素のオブジェクトを返します。

于 2009-04-01T20:03:48.800 に答える
1

複数の異なるルート要素 (例えば、WSDL で定義された XSD など) を持つ XSD 定義があり、その場合、生成されたクラスに @XmlRootElement がありません。したがって、ユーザー mbrauh がすでに書いているように、JAXBElement の値を取得する必要があります。私の場合、私は使用しました:

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

したがって、ジェネリックを使用すると、二重型キャストを簡単に回避できます。

于 2014-08-03T12:41:32.253 に答える
1

アクセス権があり、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 がルート要素を生成します。

于 2018-11-13T16:18:43.637 に答える
0

これを試して:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;
于 2016-07-15T12:46:24.797 に答える