2011-07-25 9 views
7

Chcę przekonwertować HashMap w klasie POJO na XML. Próbowałem używać XmlAdapter, ale w rezultacie tylko pary klucza i wartości w HashMap były atrybutami elementów XML. Potrzebuję klucza, aby być samym elementem, a wartość HashMap będzie wartością elementu. Na przykład, muszę następujące 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> 

stworzyłem następujące klasy: MyMapType posiada listę klasy MyMapEntryType która ma dwa pola mianowicie klucz i wartość. Jak zmienić element Key na @XmlElement i przypisać pole wartości do pola Key?


Oto moje pliki źródłowe.

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; 
} 
} 

Proszę również znaleźć klasy adaptera:

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; 
    } 
} 

Jest to klasa, która ma pole 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; 
} 


} 


Proszę doradzić, w jaki sposób to osiągnąć.

Pozdrawiam,
-Anand

Obecnie produkuje następujące dane wyjściowe:

Odpowiedz

14

Mam ten sam wymóg „Muszę być klucz do samego elementu i wartość HashMap jako wartość elementu ".

Nie użyłem dostosowanego adaptera, ale zaimplementowałem go, przekształcając wpisy HashMap dynamicznie na listę obiektów JAXBElement, a następnie przypisano listę do @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); 
    } 
} 

wyjście jest

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

+1 za bardzo interesujące i nieoczekiwane rozwiązanie robocze. – informatik01

+0

Najprostsze rozwiązanie do tej pory widziałem. Dzięki! – sinu

+0

To jest zgrabne rozwiązanie dla XML, ale niestety MOXy nie może obsłużyć tego poprawnie, gdy przekazuje do JSON w metodzie adnotacji JAX-RS.Jakoś Lista wyzwala etapowy do tablicy JSON, więc wynik wygląda mniej więcej tak: { "root": { "klucz1": [ "wartość1"], "klucz2": [ "wartość2"], "key3": ["value3"] } } Byłbym wdzięczny, gdyby ktoś wpadł na pomysł, jak to naprawić. –