这是我的工作编组代码:
对于初学者,我有一个类似于以下内容的实体类:
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public final class Entity implements {
private Map<String, Component> components = new HashMap<String, Component>();
@XmlElementWrapper(name="components")
@XmlAnyElement
public List<Component> getComponentList() {
return new ArrayList<Component>(components.values());
}
public void setComponentList(List<Component> comps) {
for(Component c : comps) {
components.put(c.getComponentType(), c);
}
}
...
}
Component
是一个非常多样化的界面,但是所有的实现都是很好的圆形bean并仔细注释。
现在,编组会产生一些外观漂亮的XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<entity>
<components>
<containerComponent>
<children>
<entity>
<components>
<containerComponent>
<children>
<entity>
<components>
<directionComponent>
<direction x="0.0" y="1.0"/>
</directionComponent>
<sizeComponent>
<size x="52.0" y="12.0"/>
</sizeComponent>
...
如您所见,每个组件类型都有自己的标记名称,但对于JAXB来说似乎不够,因为
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to tobacco.core.components.Component
at tobacco.core.components.Entity.setComponentList(Entity.java:121)
at tobacco.core.components.Entity$JaxbAccessorM_getComponentList_setComponentList_java_util_List.set(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.endPacking(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.endPacking(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.finish(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endScope(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty$ItemsLoader.leaveElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at tobacco.core.serialization.XmlEntityConverter.toEntity(XmlEntityConverter.java:32)
at tobacco.core.loader.XmlLoader.loadEntityTree(XmlLoader.java:43)
at tobacco.game.test.main.Main.main(Main.java:75)
在流程的另一端,我收到了ElementNSImpl
个对象。
我虽然使用了ObjectFactory,但在阅读和测试之后我几乎确信它没用:我找不到一种方法来访问创建者方法上的标记名称,即使我可以不那么确定JAXB会接受我的对象并快乐地填充它的属性,或者如果我必须自己填充它们,这绝对不切实际。
我认为this guy有同样的问题。它是否与MOXy开箱即用?有没有办法在不切换实现的情况下做到这一点?
答案 0 :(得分:1)
您可以使用@XmlElements注释代替@XmlAnyElement并列出所有可能的子类,例如:
@XmlElementWrapper(name = "components")
@XmlElements(
{
@XmlElement(name = "directionComponent", type = DirectionComponent.class),
@XmlElement(name = "sizeComponent", type = SizeComponent.class),
})
public List<Component> getComponentList()
{
return new ArrayList<Component>(components.values());
}
此外,在这种情况下,您无需在@XmlRootElement
和DirectionComponent
类上使用SizeComponent
注释。
PS。此外,现在您可以使用List
个组件而不是Map
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public final class Entity
{
private List<Component> components = new ArrayList<Component>();
@XmlElementWrapper(name = "components")
@XmlElements(
{
@XmlElement(name = "directionComponent", type = DirectionComponent.class),
@XmlElement(name = "sizeComponent", type = SizeComponent.class),
})
public List<Component> getComponentList()
{
return components;
}
public void setComponentList(List<Component> comps)
{
this.components = comps;
}
//...
}