JAXB:无法解组JAXBElement ,而是获取ElementNSImpl

与JAXB相关:如何实现与JAXB兼容的变体包装类? ,我尝试使用JAXBElement来表示“变体”或“任何类型”。

编组运行正常,但在Unmarshalling期间, JAXB尝试将ElementNSImpl分配给JAXBElement字段。

测试代码

(复制粘贴+ +运行)

 import static java.lang.System.*; import java.io.*; import java.util.*; import javax.xml.bind.*; import javax.xml.bind.annotation.*; import javax.xml.namespace.*; import org.junit.*; public class _JaxbElementProblem { @XmlRootElement @XmlType @XmlAccessorType(XmlAccessType.NONE) static class MyObject { public static final QName VARIANT_NAME = new QName("QQQ"); @XmlAnyElement(lax = true) private JAXBElement single = null; @XmlElementWrapper(name = "elements") @XmlAnyElement(lax = true) final List<JAXBElement> elements = new LinkedList<JAXBElement>(); @SuppressWarnings("unused") private MyObject() { } public MyObject(Object o) { single = new JAXBElement(VARIANT_NAME, Object.class, o); } public Object getSingle() { return single.getValue(); } public List getElements() { List ret = new LinkedList(); for (JAXBElement e : elements) { ret.add(e.getValue()); } return ret; } @Override public String toString() { return "MyObject (single=" + single.getValue() + "; elements: " + getElements() + ")"; } } private static final JAXBContext C; private static final Marshaller M; private static final Unmarshaller U; static { try { C = JAXBContext.newInstance(MyObject.class); M = C.createMarshaller(); U = C.createUnmarshaller(); M.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); } catch (JAXBException ex) { throw new Error(ex); } } private void testMarshalUnmarshal(Object root) throws Exception { out.println("\nMARSHALLED - - - - - - - - - - - - - - - - - - - -"); StringWriter sw = new StringWriter(); M.marshal(root, sw); out.println(sw.toString() + "\n"); out.println("\nUNMARSHALLED - - - - - - - - - - - - - - - - - - - -"); Object reunmarshalled = U.unmarshal(new StringReader(sw.toString())); out.println(reunmarshalled + "\n"); } @Before public void before() { out.println("\n= = = = = = = = = = = = = = = = = = = ="); } @Test public void test1() throws Exception { MyObject root = new MyObject(Integer.valueOf(12345)); testMarshalUnmarshal(root); } @Test public void test2() throws Exception { MyObject sub = new MyObject(Integer.valueOf(12345)); MyObject root = new MyObject(sub); testMarshalUnmarshal(root); } @Test public void test3() throws Exception { MyObject oSub = new MyObject(Integer.valueOf(12345)); List oSubs = Arrays.asList(new MyObject("sub-1"), new MyObject("sub-2"), new MyObject("sub-3")); MyObject root = new MyObject(oSub); for (MyObject o : oSubs) { root.elements.add(new JAXBElement(MyObject.VARIANT_NAME, Object.class, o)); } testMarshalUnmarshal(root); } } 

测试输出

(你可以看到,没有发生解组)

 = = = = = = = = = = = = = = = = = = = = MARSHALLED - - - - - - - - - - - - - - - - - - - -   12345   UNMARSHALLED - - - - - - - - - - - - - - - - - - - - = = = = = = = = = = = = = = = = = = = = MARSHALLED - - - - - - - - - - - - - - - - - - - -    12345     UNMARSHALLED - - - - - - - - - - - - - - - - - - - - = = = = = = = = = = = = = = = = = = = = MARSHALLED - - - - - - - - - - - - - - - - - - - -    12345     sub-1    sub-2    sub-3     UNMARSHALLED - - - - - - - - - - - - - - - - - - - - 

解组例外

 java.lang.IllegalArgumentException: Can not set javax.xml.bind.JAXBElement field my._JaxbElementProblem$MyObject.single to com.sun.org.apache.xerces.internal.dom.ElementNSImpl at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63) at java.lang.reflect.Field.set(Field.java:657) at com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.set(Accessor.java:234) at com.sun.xml.internal.bind.v2.runtime.reflect.Accessor.receive(Accessor.java:160) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:507) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:145) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194) at my._JaxbElementProblem.testMarshalUnmarshal(_JaxbElementProblem.java:84) at my._JaxbElementProblem.test3(_JaxbElementProblem.java:119) 

运行示例:

(提示:JAXBHelper来自utils-apl派生,但只是你解组和编组程序的简短forms)

 import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.junit.Test; import org.omnaest.utils.xml.JAXBXMLHelper; public class JAXBAnyElementTest { @XmlType @XmlAccessorType(XmlAccessType.FIELD) protected static class TestSubEntity { /* ********************************************** Variables ********************************************** */ @XmlElement private String fieldString = null; @XmlElement private int fieldInteger = -1; /* ********************************************** Methods ********************************************** */ /** * @see TestSubEntity */ public TestSubEntity() { super(); } /** * @see TestSubEntity * @param fieldString * @param fieldInteger */ public TestSubEntity( String fieldString, int fieldInteger ) { super(); this.fieldString = fieldString; this.fieldInteger = fieldInteger; } /** * @return the fieldString */ public String getFieldString() { return this.fieldString; } /** * @param fieldString * the fieldString to set */ public void setFieldString( String fieldString ) { this.fieldString = fieldString; } /** * @return the fieldInteger */ public int getFieldInteger() { return this.fieldInteger; } /** * @param fieldInteger * the fieldInteger to set */ public void setFieldInteger( int fieldInteger ) { this.fieldInteger = fieldInteger; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + this.fieldInteger; result = prime * result + ( ( this.fieldString == null ) ? 0 : this.fieldString.hashCode() ); return result; } @Override public boolean equals( Object obj ) { if ( this == obj ) { return true; } if ( obj == null ) { return false; } if ( !( obj instanceof TestSubEntity ) ) { return false; } TestSubEntity other = (TestSubEntity) obj; if ( this.fieldInteger != other.fieldInteger ) { return false; } if ( this.fieldString == null ) { if ( other.fieldString != null ) { return false; } } else if ( !this.fieldString.equals( other.fieldString ) ) { return false; } return true; } } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) protected static class TestEntity { @XmlElements({ @XmlElement(name = "int", type = Integer.class), @XmlElement(name = "string", type = String.class), @XmlElement(name = "testsubentity", type = TestSubEntity.class), @XmlElement(name = "other") }) private List anyElementList = null; /** * @return the anyElementList */ public List getAnyElementList() { return this.anyElementList; } /** * @param anyElementList * the anyElementList to set */ public void setAnyElementList( List anyElementList ) { this.anyElementList = anyElementList; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ( ( this.anyElementList == null ) ? 0 : this.anyElementList.hashCode() ); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals( Object obj ) { if ( this == obj ) { return true; } if ( obj == null ) { return false; } if ( !( obj instanceof TestEntity ) ) { return false; } TestEntity other = (TestEntity) obj; if ( this.anyElementList == null ) { if ( other.anyElementList != null ) { return false; } } else if ( !this.anyElementList.equals( other.anyElementList ) ) { return false; } return true; } } @SuppressWarnings("cast") @Test public void test() { // final TestEntity testEntity = new TestEntity(); // final List anyElementList = Arrays.asList( (Object) "a", Integer.valueOf( 1 ), Boolean.valueOf( true ), new TestSubEntity( "field1", 1 ) ); testEntity.setAnyElementList( anyElementList ); // final String objectAsXML = JAXBXMLHelper.storeObjectAsXML( testEntity ); System.out.println( objectAsXML ); // final TestEntity objectFromXML = JAXBXMLHelper.loadObjectFromXML( objectAsXML, TestEntity.class ); assertEquals( testEntity, objectFromXML ); } } 

输出:

   a 1 true  field1 1