2012-10-31 50 views
4

我想使用XmlAdapter調整HashMap字段的XML表示。我使用ArrayList來做到這一點。但是,編組ArrayList時根本沒有編組。這是爲什麼?JAXB編組一個由XmlAdapter創建的ArrayList

代碼

@XmlRootElement 
public class Foo { 

    private HashMap<String, String> hashMap; 

    public Foo() { 
     this.hashMap = new HashMap<String, String>(); 
    } 

    @XmlJavaTypeAdapter(HashMapAdapter.class) 
    public HashMap<String, String> getHashmap() { 
     return hashMap; 
    } 

    public void setHashmap(HashMap<String, String> hashMap) { 
     this.hashMap = hashMap; 
    } 

} 
public final class HashMapAdapter extends XmlAdapter<ArrayList<HashMapEntry>, HashMap<String, String>> { 

    @Override 
    public ArrayList<HashMapEntry> marshal(HashMap<String, String> arg0) throws Exception { 
     ArrayList<HashMapEntry> result = new ArrayList<HashMapEntry>(); 
     for(Entry<String, String> entry : arg0.entrySet()) 
      result.add(new HashMapEntry(entry.getKey(), entry.getValue())); 
     return result; 
    } 

    @Override 
    public HashMap<String, String> unmarshal(ArrayList<HashMapEntry> arg0) throws Exception { 
     HashMap<String, String> result = new HashMap<String, String>(); 
     for(HashMapEntry entry : arg0) 
      result.put(entry.key, entry.value); 
     return result; 
    } 

} 
public class HashMapEntry { 

    @XmlElement 
    public String key; 

    @XmlValue 
    public String value; 

    public HashMapEntry() { 

    } 

    public HashMapEntry(String key, String value) { 
     this.key = key; 
     this.value = value; 
    } 
} 

結果

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><hashmap/></foo> 

回答

2

在你XmlAdapter您需要將HashMap轉換爲對象的實例與List屬性,而不是直接到ArrayList

HashMapAdapter

package forum13163430; 

import java.util.*; 
import java.util.Map.Entry; 

import javax.xml.bind.annotation.*; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public final class HashMapAdapter extends XmlAdapter<HashMapAdapter.AdaptedHashMap, HashMap<String, String>> { 

    @Override 
    public AdaptedHashMap marshal(HashMap<String, String> hashMap) throws Exception { 
     AdaptedHashMap adaptedHashMap = new AdaptedHashMap(); 
     for(Entry<String, String> entry : hashMap.entrySet()) { 
      adaptedHashMap.item.add(new HashMapEntry(entry.getKey(), entry.getValue())); 
     } 
     return adaptedHashMap; 
    } 

    @Override 
    public HashMap<String, String> unmarshal(AdaptedHashMap adaptedHashMap) throws Exception { 
     HashMap<String, String> result = new HashMap<String, String>(); 
     for(HashMapEntry entry : adaptedHashMap.item) 
      result.put(entry.key, entry.value); 
     return result; 
    } 

    public static class AdaptedHashMap { 
     public List<HashMapEntry> item = new ArrayList<HashMapEntry>(); 
    } 

    public static class HashMapEntry { 

     @XmlAttribute 
     public String key; 

     @XmlValue 
     public String value; 

     public HashMapEntry() { 
     } 

     public HashMapEntry(String key, String value) { 
      this.key = key; 
      this.value = value; 
     } 
    } 

} 

更多信息


UPDATE

謝謝,這個工程。不過,我在生成的XML中獲得了額外的 註解。有什麼辦法可以避免這種情況?

如果您正在使用EclipseLink MOXy爲您JAXB (JSR-222)供應商,那麼你可以利用@XmlPath擴展這種使用情況。我將在下面舉例說明。

hashmap財產附加到@XmlJavaTypeAdapter我加入莫西的@XmlPath註解。一個"."的XML路徑指示應該將孩子編組到父母XML元素中。

package forum13163430; 

import java.util.HashMap; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
public class Foo { 

    private HashMap<String, String> hashMap; 

    public Foo() { 
     this.hashMap = new HashMap<String, String>(); 
    } 

    @XmlPath(".") 
    @XmlJavaTypeAdapter(HashMapAdapter.class) 
    public HashMap<String, String> getHashmap() { 
     return hashMap; 
    } 

    public void setHashmap(HashMap<String, String> hashMap) { 
     this.hashMap = hashMap; 
    } 

} 

jaxb.properties

要指定莫西爲您的JAXB提供你需要包括一個名爲在同一個包jaxb.properties與下面進入你的領域模型文件(見:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示

由於MOXY是JAXB(JSR-222)兼容的實現中,標準API能夠用於將對象從/到XML轉換。

package forum13163430; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Foo.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum13163430/input.xml"); 
     Foo foo = (Foo) unmarshaller.unmarshal(xml); 

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

} 

input.xml中/輸出

下面是輸入和輸出從運行演示代碼。

<?xml version="1.0" encoding="UTF-8"?> 
<foo> 
    <item key="b">B</item> 
    <item key="c">C</item> 
    <item key="a">A</item> 
</foo> 

更多信息

+0

謝謝,這個作品。不過,我在生成的XML中獲得了額外的註釋級別。有什麼辦法可以避免這種情況? – hansi

+0

@hansi - 我用一個例子說明了如何通過利用EclipseLink JAXB(MOXy)的'@ XmlPath'擴展來完成我的答案。我是MOXY的領導者。 –