Map轉化爲XML

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都是可以通過一定的方法改變的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章