How to use XmlAdapter and @XmlJavaTypeAdapter to handle Map in JAXB?
In situations where JAXB cannot handle unknown types, the solution is to create an XmlAdapter and use the @XmlJavaTypeAdapter in the class referring to the unknown type to indicate JAXB how to deal with it. A Java map is a good example.We are going to illustrate this with an example. Assuming an object containing a generic map:
@XmlRootElement public class ObjectWithGenericMap<K, V> { private Map<K,V> map; @XmlElement @XmlJavaTypeAdapter(JaxbMapAdaptor.class) public Map<K,V> getMap() { return map; } public void setMap(Map<K,V> map) { this.map = map; } }
public class JaxbMapAdaptor<K, V> extends XmlAdapter<JaxbMapToList<K, V>, Map<K, V>> { @Override public Map<K, V> unmarshal(JaxbMapToList<K, V> v) throws Exception { HashMap<K, V> result = new HashMap<K, V>(); for (JaxbMapToListEntry<K, V> jme : v.getList()) { result.put(jme.getKey(), jme.getValue()); } return result; } @Override public JaxbMapToList marshal(Map<K, V> v) throws Exception { JaxbMapToList<K, V> result = new JaxbMapToList<K, V>(); for (Map.Entry<K, V> entry : v.entrySet()) { JaxbMapToListEntry<K, V> jme = new JaxbMapToListEntry<K, V>(); jme.setKey(entry.getKey()); jme.setValue(entry.getValue()); result.getList().add(jme); } return result; } }
Basically, the above adaptor converts a map into a list of entries (with key and value) when marshalling, and converts this list of entries back into a HashMap when unmarshalling.
The map-to-list and corresponding entries are:
public class JaxbMapToList <K, V> { private List<JaxbMapToListEntry<K, V>> list = new ArrayList<JaxbMapToListEntry<K, V>>(); public JaxbMapToList() {} public JaxbMapToList(Map<K, V> map) { for (Map.Entry<K, V> e : map.entrySet()) { list.add(new JaxbMapToListEntry<K, V>(e)); } } public List<JaxbMapToListEntry<K, V>> getList() { return list; } public void setList(List<JaxbMapToListEntry<K, V>> entry) { this.list = entry; } } public class JaxbMapToListEntry<K, V> { private K key; private V value; public JaxbMapToListEntry() { } public JaxbMapToListEntry(Map.Entry<K, V> e) { key = e.getKey(); value = e.getValue(); } @XmlElement public K getKey() { return key; } public void setKey(K key) { this.key = key; } @XmlElement public V getValue() { return value; } public void setValue(V value) { this.value = value; } }
@XmlRootElement public class Destination { private String destination; public String getDestination() { return destination; } @XmlElement public void setDestination(String dest) { this.destination = dest; } } @XmlRootElement public class Transport { private String transport; public String getTransport() { return transport; } @XmlElement public void setTransport(String transp) { this.transport = transp; } } public static void main(String[] args) throws JAXBException { JAXBContext jaxbContext = JAXBContext.newInstance( ObjectWithGenericMap.class, Destination.class, Transport.class); ObjectWithGenericMap<Destination,Transport> owgm = new ObjectWithGenericMap<Destination,Transport>(); Map<Destination,Transport> map = new HashMap<Destination,Transport>(); owgm.setMap(map); Destination d = new Destination(); d.setDestination("Paris"); Transport t = new Transport(); t.setTransport("Plane"); map.put(d,t); d = new Destination(); d.setDestination("New-York"); t = new Transport(); t.setTransport("Boat"); map.put(d,t); ObjectWithGenericMap<Destination,Transport> retr = marshallingUnmarshalling(jaxbContext, owgm); for (Entry<Destination, Transport> e : retr.getMap().entrySet() ){ Destination retrd = e.getKey(); System.out.print(retrd.getDestination()); Transport retrt = e.getValue(); System.out.println(" " + retrt.getTransport()); } }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <objectWithGenericMap> <map> <list> <key xsi:type="destination" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <destination>New-York</destination> </key> <value xsi:type="transport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <transport>Boat</transport> </value> </list> <list> <key xsi:type="destination" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <destination>Paris</destination> </key> <value xsi:type="transport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <transport>Plane</transport> </value> </list> </map> </objectWithGenericMap>
Paris Plane New-York Boat
How to use: @XmlList, @XmlEnum, @XmlAttribute, @XmlValue, @XmlMimeType, @XmlInlineBinaryData?
To annotate an enum:
@XmlEnum public enum MyEnum { @XmlEnumValue("v1") VAL_1, @XmlEnumValue("v2") VAL_2; }
@XmlAccessorType(XmlAccessType.FIELD) public class SpecialItem { @XmlValue private String val; @XmlAttribute private String attribute1; @XmlAttribute private String attribute2; // Setter & Getters... }
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement public class MultipleTypes { @XmlElement private MyEnum myEnum; @XmlElement @XmlList private List<String> data; @XmlElement private List<SpecialItem> specialItems; @XmlMimeType("image/jpeg") private Image image; @XmlInlineBinaryData private byte[] byteArray; // Setter & Getters... }
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <multipleTypes> <myEnum>v2</myEnum> <data>tre pml xng</data> <specialItems attribute2="ffff" attribute1="aaaa">pppp</specialItems> <specialItems attribute2="pqgd" attribute1="mer">xxw</specialItems> <image>/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAALABADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwCxBe6S1ha3ptg4MEYF29lGSXKA5JIznHvmuX1UaCmhapbwxW2023mxkWUSyedsbjPXaOTkdPX+9wieM/EEOlrpkeoEWS7SIfKQj5Rgfw88AflUb+JdVl0O7tHniMMkqbh9njDcq4Pzbcjj0PrXppRo3SuTVqVKrV7aH//Z</image> <byteArray>AQL9/A==</byteArray> </multipleTypes>
pppp aaaa ffff xxw mer pqgd VAL_2 tre, pml, xng, 1 2 -3 -4 Image is available: true
Remark
We have not covered all JAXB annotations, especially those related to XML schemas, but this tutorial should be enough to get one started and accomplish most objectives with JXTA.JAXB to XML • JAXB to JSON • JAXB Annotations Tutorial Table Of Content
Nice ... very Useful :)
ReplyDelete