首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有基类的Jaxb不序列化派生元素

带有基类的Jaxb不序列化派生元素
EN

Stack Overflow用户
提问于 2018-10-09 17:35:05
回答 1查看 79关注 0票数 0

我有一个树状结构的模块列表。基类包含childs和一些泛型属性,而派生类应该提供它的各个字段。现在,当我尝试用JAXB序列化它时,我只得到基类的成员,而不是来自派生类的成员。

Application.java

代码语言:javascript
复制
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Application
{
    public static void main(String[] args)
    {
        try
        {
            Emulators emulators = new Emulators();
            emulators.addChild(new VICEModule());
            emulators.addChild(new VICEModule());

            StringWriter sw = new StringWriter();
            JAXBContext jaxbContext = JAXBContext.newInstance(emulators.getClass());
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Pretty print
            jaxbMarshaller.marshal(emulators, sw);
            String s = sw.toString();
            System.out.println(s);
        }
        catch(Throwable e)
        {
            System.err.println("Exception:"+e);
        }
    }
}

ModuleBase.java

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;

import com.sun.xml.internal.txw2.annotation.XmlAttribute;

public class ModuleBase
{
    private List<ModuleBase> mChilds = new ArrayList<>();
    private String mModuleId;
    private String mModuleName;

    public ModuleBase(String oModuleId, String oModuleName)
    {
        setModuleId(oModuleId);
        setModuleName(oModuleName);
    }

    public void addChild(ModuleBase oModuleNode)
    {
        mChilds.add(oModuleNode);
    }

    @XmlElement(name="ModuleList")
    public List<ModuleBase> getChildModules()
    {
        return mChilds;
    }

    @XmlAttribute
    public String getModuleId()
    {
        return mModuleId;
    }

    public void setModuleId(String oModuleId)
    {
        mModuleId = oModuleId;
    }

    @XmlAttribute
    public String getModuleName()
    {
        return mModuleName;
    }

    public void setModuleName(String oModuleName)
    {
        mModuleName = oModuleName;
    }
}

Emulators.java

代码语言:javascript
复制
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Emulators")
public class Emulators
    extends ModuleBase 
{
    public Emulators()
    {
        super("IdEmu129872q53", "Emulators");
    }
}

VICEModule.java

代码语言:javascript
复制
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name = "VICEModule")
public class VICEModule
    extends ModuleBase
{
    private String mInstallationPath;
    private int mPort;

    public VICEModule()
    {
        super("Id123456", "Vice");

        mPort = 6510;
    }

    //@XmlElement(name="InstallationPath")
    @XmlValue
    public String getInstallationPath()
    {
        return mInstallationPath;
    }

    public void setInstallationPath(String oPath)
    {
        mInstallationPath = oPath;
    }

    //@XmlElement(name="Port")
    @XmlValue
    public int getPort()
    {
        return mPort;
    }

    public void setPort(int nPort)
    {
        mPort = nPort;
    }
}

现在,当我序列化它时,我得到了以下VICEModule,其中缺少XML值,并且模块被列为ModuleList而不是VICEModule,并且基本字段被作为标记而不是属性来放置:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators>
    <ModuleList>
        <moduleId>Id123456</moduleId>
        <moduleName>Vice</moduleName>
    </ModuleList>
    <ModuleList>
        <moduleId>Id123456</moduleId>
        <moduleName>Vice</moduleName>
    </ModuleList>
    <moduleId>IdEmu129872q53</moduleId>
    <moduleName>Emulators</moduleName>
</Emulators>

所以这应该是这样的:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators ModuleId="IdEmu129872q53" ModuleName="Emulators">
    <VICEModule ModuleId="Id1" ModuleName="Name">
        <InstallationPath>Path1</InstallationPath>
        <Port>6510</Port>
    </VICEModule>
    <VICEModule ModuleId="Id2" ModuleName="Name">
        <InstallationPath>Path2</InstallationPath>
        <Port>6511</Port>
    </VICEModule>
</Emulators>

当我使用VICEModule作为基类时,它看起来更像它(尽管仍然没有属性)。

EN

回答 1

Stack Overflow用户

发布于 2018-10-09 20:15:58

编写这个小的演示应用程序很有帮助,因为现在我可以更容易地处理编组,并最终让它工作。我在这里发布了这些更改,以使此示例完整,以防有人需要它作为参考。Emulators.java没有更改,所以它没有列在答案中。

简短的回答:

我必须将@XmlAnyElement(lax=true)添加到子模块的getter中,以便将生成的XML节点转换为我想要的命名节点。此外,在主应用程序中,我必须遍历树并收集所有使用的类,以便将其传递给JAXBContext

Application.java

代码语言:javascript
复制
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Application
{
    public static List<Class<?>> createClasses(ModuleBase oModule)
    {
        List<Class<?>> classes = new ArrayList<>();
        classes.add(oModule.getClass());

        for(ModuleBase module : oModule.getChildModules())
        {
            List<Class<?>> cls = createClasses(module);
            classes.addAll(cls);
        }

        return classes;
    }

    public static void main(String[] args)
    {
        try
        {
            Emulators emulators = new Emulators();
            emulators.addChild(new VICEModule("Id1", "VICE V1", "V1 Path", 6510));
            emulators.addChild(new VICEModule("Id2", "VICE V2", "V2 Path", 6511));

            StringWriter sw = new StringWriter();
            List<Class<?>> classes = createClasses(emulators);
            Class<?>[] cls = new Class<?>[classes.size()];
            for(int i = 0; i < classes.size(); i++)
                cls[i] = classes.get(i);

            JAXBContext jaxbContext = JAXBContext.newInstance(cls);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Pretty print
            jaxbMarshaller.marshal(emulators, sw);
            String s = sw.toString();
            System.out.println(s);
        }
        catch(Throwable e)
        {
            System.err.println("Exception:"+e);
        }

        return;
    }
}

ModuleBase.java

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;

public class ModuleBase
{
    private List<ModuleBase> mChilds = new ArrayList<>();

    private String mModuleId;
    private String mModuleName;

    public ModuleBase(String oModuleId, String oModuleName)
    {
        setModuleId(oModuleId);
        setModuleName(oModuleName);
    }

    public void addChild(ModuleBase oModuleNode)
    {
        mChilds.add(oModuleNode);
    }

    @XmlAnyElement(lax=true)
    public List<ModuleBase> getChildModules()
    {
        return mChilds;
    }

    @XmlAttribute
    public String getModuleId()
    {
        return mModuleId;
    }

    public void setModuleId(String oModuleId)
    {
        mModuleId = oModuleId;
    }

    @XmlAttribute
    public String getModuleName()
    {
        return mModuleName;
    }

    public void setModuleName(String oModuleName)
    {
        mModuleName = oModuleName;
    }
}

VICEModule.java

代码语言:javascript
复制
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "VICEModule")
public class VICEModule
    extends ModuleBase
{
    private String mInstallationPath;
    private int mPort;

    public VICEModule()
    {
        super("Id123456", "Vice");

        mPort = 6510;
    }

    public VICEModule(String oId, String oName, String oPath, int nPort)
    {
        super(oId, oName);

        setInstallationPath(oPath);
        setPort(nPort);
    }

    @XmlElement(name="InstallationPath")
    public String getInstallationPath()
    {
        return mInstallationPath;
    }

    public void setInstallationPath(String oPath)
    {
        mInstallationPath = oPath;
    }

    @XmlElement(name="Port")
    public int getPort()
    {
        return mPort;
    }

    public void setPort(int nPort)
    {
        mPort = nPort;
    }
}

现在,通过存储派生类中的所有对象,XML完全按照预期呈现。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators moduleId="IdEmu129872q53" moduleName="Emulators">
    <VICEModule moduleId="Id1" moduleName="VICE V1">
        <InstallationPath>V1 Path</InstallationPath>
        <Port>6510</Port>
    </VICEModule>
    <VICEModule moduleId="Id2" moduleName="VICE V2">
        <InstallationPath>V2 Path</InstallationPath>
        <Port>6511</Port>
    </VICEModule>
</Emulators>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52717768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档