JAXB不会解组我以前编组过的界面impls

时间:2014-08-19 01:24:40

标签: java xml jaxb

这是我的工作编组代码:

对于初学者,我有一个类似于以下内容的实体类:

@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开箱即用?有没有办法在不切换实现的情况下做到这一点?

1 个答案:

答案 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());
}      

此外,在这种情况下,您无需在@XmlRootElementDirectionComponent类上使用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;
    }
    //...
}