2011-07-25 9 views
7

POJOクラスのHashMapをXMLに変換したいと考えています。私はXmlAdapterを使用しようとしましたが、XML要素の属性であるHashMapのキーと値の組だけが返されます。 Element自体のKeyと、要素の値になるHashMapの値が必要です。例えば、私は、次のXMLが必要ですJAXB HashMap unmappable

<?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はすなわち、キーと値の2つのフィールドがあり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配列にマーシャリングをトリガするので、結果はこのようなものになります。 { "ルート": { "キー1":[ "VALUE1"]、 "KEY2":[ "値2"]、 を"key3":["value3"] } } この問題を解決する方法があれば、感謝しています。 –

0

注:Map例えばマーシャル/アンマーシャリングの例では、ここで見つけることができる:Dynamic tag names with JAXB