使用Moxy处理动态元素名称

时间:2014-06-10 10:21:53

标签: java json jaxb moxy

我需要对我的对象FileDocument进行绑定,该对象包含对另一个对象Metadata的引用。元数据 - 我希望 - 可以根据其属性的值来拥有动态名称。

我听过并使用过XmlAdapter(也用于元数据类),但仅适用于Map案例。我真的不明白如何使它适用于这种情况。

FileDocument片段:

@XmlAccessorType(XmlAccessType.FIELD)
public class FileDocument{
//...
 protected List<Metadata> metadata;
//...
}

元数据摘录:

@XmlType(name = "metadata")
//@XmlRootElement(name = "metaCollection")
public class Metadata {
//...
    @XmlPath(".")
    @XmlJavaTypeAdapter(MetaAdapter.class)
    Map<String, String> map;
    //I'd like to have each element of metadata depend on this attribute.
    String source;

}

我想要的输出类似于

{ 
   "someKeyInFileDocument" : "someValueInFileDocument",
   "metadata.source1" : {
      "some key inside this metadata" : "some value inside this metadata",
      "more!": "more!"
    },
   "metadata.source2" : {
     "yes, the above key" : "looks similar but also different as the above",
     "this is another key!" : "inside this source2 thing"
   }
}

1 个答案:

答案 0 :(得分:3)

对于此用例,您可以使用EclipseLink JAXB (MOXy)@XmlVariableNode扩展名:

Java模型

<强> FileDocument

我们将在@XmlVariableNode字段上使用metadata注释。这告诉MOXy,不要使用元素/键的固定名称,而应该从引用对象的指定字段/属性中获取名称。

import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;

@XmlAccessorType(XmlAccessType.FIELD)
public class FileDocument {

    @XmlVariableNode("source")
    protected List<Metadata> metadata;

}

<强>元数据

我们将使用@XmlTransient字段上的source注释来阻止它被编组(请参阅:http://blog.bdoughan.com/2012/04/jaxb-and-unmapped-properties.html)。

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Metadata {

    @XmlTransient
    String source;

}

演示代码

您可以运行下面的演示代码,看看一切正常。

<强>演示

import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {FileDocument.class}, properties);


        Metadata m1 = new Metadata();
        m1.source = "metadata.source1";

        Metadata m2 = new Metadata();
        m2.source = "metadata.source2";

        List<Metadata> metadata = new ArrayList<Metadata>();
        metadata.add(m1);
        metadata.add(m2);

        FileDocument fd = new FileDocument();
        fd.metadata = metadata;

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(fd, System.out);
    }

}

<强>输出

{
   "metadata.source1" : {
   },
   "metadata.source2" : {
   }
}

更多信息

您可以在我的博客上详细了解@XmlVariableNode扩展程序: