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
输出:
a 1 true field1 1