2011-07-25 156 views
7

我想将POJO类中的HashMap转换为XML。我尝试过使用XmlAdapter,但它只导致HashMap的键和值对作为XML元素的属性。我需要Key作为元素本身,而HashMap的值是元素的值。举例来说,我需要以下XML:JAXB HashMap无法映射

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<cart> 
<supervisor_id>555</supervisor_id> 
<payments> 
    <payment sequence="1"> 
     <amount>123.45</amount> 
     <billing_method>12345</billing_method> 
     <form>card</form> 
     <delivery_mode>Q</delivery_mode> 
    </payment> 
<payment sequence="2"> 
     <amount>123.45</amount> 
     <person_id>2333</person_id> 
     <form>cash</form> 
     <delivery_mode>Q</delivery_mode> 
    </payment> 
</payments> 
</cart> 

我创建了以下类:MyMapType持有它有两个字段,即键和值MyMapEntryType类的列表。如何将Key元素更改为@XmlElement并将值字段分配给Key字段?


这是我的源文件。

MyMapType.java

import java.util.ArrayList; 
import java.util.List; 

public class MyMapType { 

    private List<MyMapEntryType> entry = new ArrayList<MyMapEntryType>(); 

    public List<MyMapEntryType> getEntry() { 
     return entry; 
    } 

    public void setEntry(List<MyMapEntryType> entry) { 
     this.entry = entry; 
    } 

} 

MyMapEntryType.java

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlValue; 

@XmlAccessorType(XmlAccessType.FIELD) 
public class MyMapEntryType { 

@XmlAttribute 
private String key; 
@XmlValue 
private String value; 
public String getKey() { 
    return key; 
} 
public void setKey(String key) { 
    this.key = key; 
} 
public String getValue() { 
    return value; 
} 
public void setValue(String value) { 
    this.value = value; 
} 
} 

还请找到适配器类:

MyMapAdapter.java

import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class MyMapAdapter extends XmlAdapter<MyMapType, Map<String, String>> { 

    @Override 
    public MyMapType marshal(Map<String, String> map) throws Exception { 

     MyMapType myMapType = new MyMapType(); 

     for(Entry<String, String> entry : map.entrySet()) { 
     MyMapEntryType myMapEntryType = new MyMapEntryType(); 
     myMapEntryType.setKey(entry.getKey()); 
     myMapEntryType.setValue(entry.getValue()); 
     myMapType.getEntry().add(myMapEntryType); 
     } 
     return myMapType; 
    } 

    @Override 
    public Map<String, String> unmarshal(MyMapType map) throws Exception { 
     HashMap<String, String> hashMap = new HashMap<String, String>(); 
     for(MyMapEntryType myEntryType : map.getEntry()) { 
     hashMap.put(myEntryType.getKey(), myEntryType.getValue()); 
     } 
     return hashMap; 
    } 
} 

这是一个有HashMap的领域类:

XmlElementMap.java

@XmlAccessorType(XmlAccessType.FIELD) 
public class XmlElementMap { 

@XmlAttribute(name="sequence") 
private int sequence; 

@XmlJavaTypeAdapter(MyMapAdapter.class) 
private Map<String, String> map = new HashMap<String, String>(); 

public int getSequence() { 
    return sequence; 
} 

public void setSequence(int sequence) { 
    this.sequence = sequence; 
} 

public Map<String, String> getMap() { 
    return map; 
} 

public void setMap(Map<String, String> map) { 
    this.map = map; 
} 


} 


请就如何实现这一目标的建议。

问候,
-Anand

目前,它产生以下输出:

回答

14

我有同样的要求,“我需要的关键是元素本身和HashMap的是价值的价值元素“。

我没有使用自定义的适配器,而是通过将HashMap条目动态地转换为JAXBElement对象列表来实现它,然后使用@XmlAnyElement对列表进行注释。

@XmlRootElement(name="root") 
public class MyMapType { 

    @XmlAnyElement 
    public List<JAXBElement> entries = new ArrayList<JAXBElement>(); 

    public MyMapType() { // JAXB required  
    } 

    public MyMapType(Map<String, String> map) { 
     for (Map.Entry<String, String> entry : map.entrySet()) { 
      entries.add(new JAXBElement(new QName(entry.getKey()), 
        String.class, entry.getValue())); 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     JAXBContext context = JAXBContext.newInstance(MyMapType.class); 
     Marshaller marshaller = context.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     Map<String, String> map = new LinkedHashMap<String, String>(); 
     map.put("key1", "value1"); 
     map.put("key2", "value2"); 
     MyMapType mt = new MyMapType(map); 

     marshaller.marshal(mt, System.out); 
    } 
} 

输出是,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root> 
    <key1>value1</key1> 
    <key2>value2</key2> 
</root> 
+0

+1非常有趣和意想不到的工作解决方案。 – informatik01

+0

迄今为止我所见过的最简单的解决方案。谢谢! – sinu

+0

这是一个很好的XML解决方案,但不幸的是,在JAX-RS注释方法中编组为JSON时,MOXy似乎无法正确处理此问题。以某种方式列表触发编组到JSON数组,所以结果看起来是这样的: { “根”: { “KEY1”:[ “VALUE1”], “KEY2”:[ “VALUE2”], “key3”:[“value3”] } } 如果有人有一个想法如何解决这个问题,我将不胜感激。 –