用来记录一些原创性的总结
在上一篇博文中,我们使用了一个自定义的XmlMap类用以封装类似于Map的结构以存储数据,然后把它转换为XML。但是它的结构比较简单,如果我们需要使用真实的Map的话,我们需要把我们的XmlMap实现java.util.Map接口,然后实现其中的各个方法并把它们转换为ArrayList中的一个元素。这显然是比较麻烦的。为此笔者提供了一种把真实的Map转换为XML的方法,而不是直接使用自定义的XmlMap。大体思路是定义一个XmlAdapter,把一个真实类型的Map转换为XmlMap,然后在转换为XML时还是根据XmlMap来进行转换,这对它的使用者来讲会更加的友好。使用者不用关心是怎么转换的,只需要按照正常的逻辑使用Map结构即可。
定义了一个MapAdapter,其实现如下:
public static class MapAdapter extends XmlAdapter<XmlMap, Map<String, String>> {
@Override
public Map<String, String> unmarshal(XmlMap v) throws Exception {
return null;
}
@Override
public XmlMap marshal(Map<String, String> v) throws Exception {
if (v != null) {
XmlMap xmlMap = new XmlMap();
for (Map.Entry<String, String> entry : v.entrySet()) {
xmlMap.put(entry.getKey(), entry.getValue());
}
return xmlMap;
}
return null;
}
}
然后XmlMap的结构也要改一改,不再继承自ArrayList,而是直接持有一个List类型的属性,因为使用了XMLAdapter后,XmlMap会被直接当做一个对象进行转换,而不是像方法一那样被当做一个集合来进行转换。因此为了确保其能够正确的输出key/value形式的元素,我们将XmlMap改造为如下这样。
@XmlAccessorType(XmlAccessType.FIELD)
public static class XmlMap {
@XmlElementRef(name="xmlMap")
private List<JAXBElement<String>> elements = new ArrayList<>();
private static ObjectFactory objectFactory = new ObjectFactory();
public void put(String key, String value) {
JAXBElement<String> ele = objectFactory.createXmlMap(key, value);
this.elements.add(ele);
}
}
ObjectFactory的内容还是不变。然后Request中的condition定义为java.util.Map类型。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Request {
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, String> condition;
@Override
public String toString() {
return "Request [condition=" + condition + "]";
}
}
测试代码如下:
@Test
public void test() throws Exception {
Request request = new Request();
Map<String, String> condition = new LinkedHashMap<>();
for (int i=0; i<5; i++) {
condition.put("key_" + i, "value_" + i);
}
request.condition = condition;
JAXBContext jaxbContext = JAXBContext.newInstance(Request.class, ObjectFactory.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(request, System.out);
}
输出结果如下:
<request>
<condition>
<key_0>value_0</key_0>
<key_1>value_1</key_1>
<key_2>value_2</key_2>
<key_3>value_3</key_3>
<key_4>value_4</key_4>
</condition>
</request>
也正常的按照我们想要的Map结构进行了输出。以下是完整代码。
@Test
public void test() throws Exception {
Request request = new Request();
Map<String, String> condition = new LinkedHashMap<>();
for (int i=0; i<5; i++) {
condition.put("key_" + i, "value_" + i);
}
request.condition = condition;
JAXBContext jaxbContext = JAXBContext.newInstance(Request.class, ObjectFactory.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(request, System.out);
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Request {
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, String> condition;
@Override
public String toString() {
return "Request [condition=" + condition + "]";
}
}
public static class MapAdapter extends XmlAdapter<XmlMap, Map<String, String>> {
@Override
public Map<String, String> unmarshal(XmlMap v) throws Exception {
return null;
}
@Override
public XmlMap marshal(Map<String, String> v) throws Exception {
if (v != null) {
XmlMap xmlMap = new XmlMap();
for (Map.Entry<String, String> entry : v.entrySet()) {
xmlMap.put(entry.getKey(), entry.getValue());
}
return xmlMap;
}
return null;
}
}
@XmlRegistry
public static class ObjectFactory {
@XmlElementDecl(name="xmlMap")
public JAXBElement<String> createXmlMap(String key, String value) {
QName name = new QName(key);
JAXBElement<String> ele = new JAXBElement<>(name, String.class, value);
return ele;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
public static class XmlMap {
@XmlElementRef(name="xmlMap")
private List<JAXBElement<String>> elements = new ArrayList<>();
private static ObjectFactory objectFactory = new ObjectFactory();
public void put(String key, String value) {
JAXBElement<String> ele = objectFactory.createXmlMap(key, value);
this.elements.add(ele);
}
}
(注:本文由Elim写于2017年8月9日)