Map轉化爲XML
1. Map節點的名稱不變更
ProductObject類:
package com.liantuo.contrast.util.jaxb;
import javax.xml.bind.annotation.*;
import java.util.List;
import java.util.Map;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class ProductObject {
@XmlAttribute
private Integer id;
@XmlAttribute
private String name;
private Map<String,String> item;
...... get/set方法
}
Map轉化爲XML方法:
package com.liantuo.contrast.util.jaxb;
import org.apache.commons.collections.map.HashedMap;
import javax.xml.bind.JAXB;
import java.util.Map;
public class testMap {
public static void main(String[] args) {
ProductObject productObject = new ProductObject();
productObject.setId(1);
productObject.setName("apple");
Map<String,String> map = new HashedMap();
map.put("name","Apple Pay");
map.put("price","4000");
productObject.setItem(map);
JAXB.marshal(productObject, System.out);
}
}
XML結果:
通過結果可以得出每一組Map數據被解析成了<entry>、<key>、<value>結構,通過之前的知識,改變<product>節點下的<id>、<item>的值是可以輕鬆做到的.而這裏的<key>、<value>並不是我們希望顯示的節點名稱,這就需要進行改造了.
2. Map節點的名稱變更
改造需要的代碼量比較多,因爲JAXB原生不指定Map的自定義操作.也可以說JAXB不支持Map這種數據類型.所以需要使用到適配器來擴展Jaxb的功能.
首先定義一個類,其中只有兩個字段,爲了簡單,可以不寫setters/getters方法.通過這種方式模擬一個Map,只包含key/value,也就是first/second,這個名稱就是XML的節點顯示名稱.
XmlMap實體類:
package com.liantuo.contrast.util.jaxb;
public class XmlMap {
public String first;
public String second;
}
自定義一個Adapter,命名爲MapAdapter
package com.liantuo.contrast.util.jaxb;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.HashMap;
import java.util.Map;
public class MapAdapter extends XmlAdapter<XmlMap[], Map<String, String>> {
@Override
public Map<String, String> unmarshal(XmlMap[] v) throws Exception {
Map<String, String> map = new HashMap<>();
for(int i=0;i<v.length;i++) {
XmlMap pairs = v[i];
map.put(pairs.first, pairs.second);
}
return map;
}
@Override
public XmlMap[] marshal(Map<String, String> v) throws Exception {
XmlMap[] xmlMap = new XmlMap[v.size()];
int index = 0;
for(Map.Entry<String, String> entry: v.entrySet()) {
XmlMap xm = new XmlMap();
xm.first = entry.getKey();
xm.second = entry.getValue();
xmlMap[index++] = xm;
}
return xmlMap;
}
}
@XmlJavaTypeAdapterJAXB能夠內置支持List和Set集合,但是對於Map的支持需要自己處理.它繼承自抽象類XmlAdapter<ValueType,BoundType>類型參數:
BoundType JAXB不知道如何處理的一些類型.自定義的類型,告訴Jaxb ValueType將此類型用作內存表示形式.
ValueType JAXB無需其他操作便知道如何處理的類型.
這裏的Map對於JAXB是一個未知類型,但是XmlMap[]卻是已知的對象數組類型.通過中間的轉化賦值,可以使XmlMap[]與Map相互轉化,從而讓Jaxb知道數據如何處理.
ProductObject實體類:
package com.liantuo.contrast.util.jaxb;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Map;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class ProductObject {
@XmlAttribute
private Integer id;
@XmlAttribute
private String name;
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> goods;
...... get/set方法
}
在之前的ProductObject類中的Map上加上註解@XmlJavaTypeAdapter(MapAdapter.class).
Map轉化爲XML方法:
package com.liantuo.contrast.util.jaxb;
import org.apache.commons.collections.map.HashedMap;
import javax.xml.bind.JAXB;
import java.util.Map;
public class testMap {
public static void main(String[] args) {
ProductObject productObject = new ProductObject();
productObject.setId(1);
productObject.setName("apple");
Map<String,String> map = new HashedMap();
map.put("name","Apple Pay");
map.put("price","4000");
productObject.setGoods(map);
JAXB.marshal(productObject, System.out);
}
}
XML結果:
上面的所有節點名稱除了item都是可以通過一定的方法改變的