2つのコードがあり、2つの異なるJavaプロジェクトで、ほぼ同じことをしています(xsd-fileに従ってWebサービスの入力を非整列化))。
しかし、ある場合にはこれを書く必要があります:(入力はプレースホルダー名です)(要素はOMElement入力です)
ClassLoader clInput = input.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("input", clInput);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Input input = (Input)unmarshaller.unmarshal( element.getXMLStreamReader() );
もう1つのlibではJAXBElement.getValue()を使用する必要があります。これは、返されるのがJAXBElementであり、単純な(入力)キャストが単にクラッシュするためです。
Input input = (Input)unmarshaller.unmarshal( element.getXMLStreamReader() ).getValue();
何がそのような違いにつながるのか知っていますか?
ルート要素がJavaクラスに一意に対応している場合は、そのクラスのインスタンスが返され、そうでない場合はJAXBElement
が返されます。
常にドメインオブジェクトのインスタンスを取得したい場合は、JAXBInstrospector
を利用できます。以下に例を示します。
デモ
package forum10243679;
import Java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
private static final String XML = "<root/>";
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBIntrospector jaxbIntrospector = jc.createJAXBIntrospector();
Object object = unmarshaller.unmarshal(new StringReader(XML));
System.out.println(object.getClass());
System.out.println(jaxbIntrospector.getValue(object).getClass());
Object jaxbElement = unmarshaller.unmarshal(new StreamSource(new StringReader(XML)), Root.class);
System.out.println(jaxbElement.getClass());
System.out.println(jaxbIntrospector.getValue(jaxbElement).getClass());
}
}
出力
class forum10243679.Root
class forum10243679.Root
class javax.xml.bind.JAXBElement
class forum10243679.Root
ルート要素のクラスに XmlRootElementアノテーション が存在するかどうかに依存します。
XSDからJAXBクラスを生成する場合、次のルールが適用されます。
そのため、ルート要素には匿名タイプを選択することがよくあります。
この匿名型のクラス名は、カスタマイズファイルを使用してカスタマイズできます。例えば。次のようにbindings.xjcファイルを作成します。
<jxb:bindings version="1.0"
xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="yourXsd.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[@name='yourRootElement']">
<jxb:class name="YourRootElementType"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
適切なJAXB生成クラスに@XMLRootElement
を追加する必要があります-名前空間が必要です:
@XmlRootElement(namespace="http://your.namespace.com/", name="yourRootElement")
関連する質問を見てください(良いヒントがたくさんあります): XMLを非整列化しようとするとClass Cast Exception?
私は同じ問題を抱えています。 JAXB unmarshaller.unmarshalは、目的のMyObject
ではなくJAXBElement<MyObject>
を返します。
@XmlElementDecl
を見つけて削除しました。問題は解決された。
生成されたJavaクラスの変更、同意しません。すべての可能なxsd形式を許可するわけではないので、同意しません。
すべての説明とリンクに感謝します。これは、Annotation Introspectionを使用して両方のケースを処理するために私が作成したコードです。入力だけでなく出力でも機能し、(私の好みでは)より一般的です:
public class JaxbWrapper {
private static boolean isXmlRootElement(Class classT){
Annotation[] annotations = classT.getAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof XmlRootElement){
return true;
}
}
return false;
}
public static Object unmarshall(Class classObjectFactory, Class classObject, XMLStreamReader xmlStreamReader){
Package pack = classObjectFactory.getPackage();
String strPackageName = pack.getName();
Object returnObject = null;
try {
JAXBContext jc = JAXBContext.newInstance(strPackageName, classObjectFactory.getClassLoader());
Unmarshaller unmarshaller = jc.createUnmarshaller();
returnObject = unmarshaller.unmarshal( xmlStreamReader );
boolean bIsRootedElement = isXmlRootElement(classObject);
if(!bIsRootedElement)
{
JAXBElement jaxbElement = (JAXBElement) returnObject;
returnObject = jaxbElement.getValue();
}
}
catch (JAXBException e) {
/*...*/
}
return returnObject;
}
private static void writeToXml(Class classObjectFactory, Object obj, XMLStreamWriter xmlStreamWriter){
Package pack = classObjectFactory.getPackage();
String strPackageName = pack.getName();
try {
JAXBContext jc = JAXBContext.newInstance(strPackageName, classObjectFactory.getClassLoader());
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(obj, xmlStreamWriter);
}
catch(JAXBException e) {
/*...*/
}
}
public static String marshall(Class classObjectFactory, Class classObject, Object obj){
Object objectToMarshall = obj;
boolean bIsRootedElement = isXmlRootElement(classObject);
if(!bIsRootedElement)
{
Package pack = classObjectFactory.getPackage();
String strPackageName = pack.getName();
String strClassName = classObject.getName();
QName qName = new QName(strPackageName, strClassName);
JAXBElement jaxbElement = new JAXBElement(qName, classObject, null, obj);
objectToMarshall = jaxbElement;
}
StringWriter sw = new StringWriter();
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter xmlStreamWriter = null;
try {
xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(sw);
writeToXml(classObjectFactory, objectToMarshall, xmlStreamWriter);
xmlStreamWriter.flush();
xmlStreamWriter.close();
}
catch (XMLStreamException e) {
/*...*/
}
return sw.toString();
}
}