如何在运行时使用MOXy封送List中对象的特定字段

时间:2013-12-12 15:52:00

标签: java jaxb eclipselink marshalling moxy

我需要将一个集合列表封送到xml,但我希望用户选择从List的对象中封送哪些字段。这是对我想要做的更好的解释。

首先,我有一个名为服务器

的POJO
@XmlAccessorType(XmlAccessType.FIELD)
public class Server {

    @XmlElement(nillable=true)  private String vendor;
    @XmlElement(nillable=true)  private int memory;
    @XmlElement(nillable=true)  private String cpu;
//getters and setters
}

然后在我的应用程序中,我有这个方法正在执行元帅工作。 请注意,此实现基于此Creating a Generic List Wrapper in JAXB

MOXy's Object Graphs - Partial Models on the Fly to/from XML & JSON

    protected void marshalCollection(Object collection,OutputStream os) throws Exception {
        //The output list contains the name of the Server.class fields to be                           
        //marshaled
        List<String> output = (List<String>) getContext()
                .getHttpServletRequest().getAttribute("output");

        Class<?> cls = Class.forName("my.package.Server");

        //This list contains the Server objects to be marshaled
        List ls = (List) collection;

        JAXBContext jc = JAXBContext.newInstance(Wrapper.class, cls);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        QName qName = new QName("servers");
        Wrapper wrapper = new Wrapper(ls);
        JAXBElement<Wrapper> jaxbElement = new JAXBElement<Wrapper>(qName,
                Wrapper.class, wrapper);

        ObjectGraph outputInfo = JAXBHelper.getJAXBContext(jc)
                .createObjectGraph(Wrapper.class);

        Subgraph subg = outputInfo.addSubgraph("server");

        for (String o : output) {
            subg.addAttributeNodes(o);
        }

        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, outputInfo);
        marshaller.marshal(jaxbElement, os);

    }

这是我的Wrapper类

public class Wrapper<T> {

    @XmlAnyElement(lax=true)
    private List<T> items;

    public Wrapper() {
        items = new ArrayList<T>();
    }

    public Wrapper(List<T> items) {
        this.items = items;
    }


    public List<T> getItems() {
        return items;
    }

}

不幸的是我得到了一个空的xml

<?xml version="1.0" encoding="UTF-8"?>
<servers/>

我想要回来的一个例子是

如果输出列表包含“memory”和“cpu”且 ls 列表包含两个服务器对象

Server[vendor=HP,memory=4096,cpu=intel]
Server[vendor=IBM,memory=2048,cpu=amd]

然后我要回来的xml是

<?xml version="1.0" encoding="UTF-8"?>
<servers>
    <server>
        <memory>4096</memory>
        <cpu>intel</cpu>
    </server>
    <server>
        <memory>2048</memory>
        <cpu>amd</cpu>
    </server>
</servers>

任何人都可以帮我找到我做错的事吗? 有没有其他方法可以编组列表中我的服务器对象中的选定字段?

由于

1 个答案:

答案 0 :(得分:1)

您在MOXy中使用@XmlAnyElement(lax=true)处理对象图的方式遇到了错误。您可以使用以下错误来跟踪我们在此问题上的进展。

解决方法

对于此用例,您可以将JAXB与StAX结合使用。 StAX将用于编写包装器元素,然后您可以将Server的各个实例封送到它。请注意对象图的创建方式稍有变化。

    XMLOutputFactory xof = XMLOutputFactory.newFactory();
    XMLStreamWriter xsw = xof.createXMLStreamWriter(System.out);
    xsw.writeStartDocument();
    xsw.writeStartElement("servers");

    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

    ObjectGraph outputInfo = JAXBHelper.getJAXBContext(jc)
        .createObjectGraph(Server.class);
    for (String o : output) {
        outputInfo.addAttributeNodes(o);
    }

    marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, outputInfo);

    for(Object item : ls) {
        marshaller.marshal(item, xsw);
    }
    xsw.writeEndElement();
    xsw.writeEndDocument();
    xsw.close();