JAXB @XmlAdapter: Map & # 8594; List of adapters? (only marshall)

I have a Map<String, String> .
The first idea is to convert it to List<Pair<String,String>> ( Pair as a custom class).

I tried @XmlAdapter as follows:

 public class MapPropertiesAdapter extends XmlAdapter<List<Property>, Map<String,String>> { ... } 

But Eclipse MOXy, the JAXB I'm using, ended up with a ClassCastException - "cannot convert a HashMap to a collection."

Is this JAXB conversion supported? Or did I not notice part of the documentation that explains why this is not so?

PS: I wanted to get XML as follows:

 <properties> <property name="protocol"/> <property name="marshaller"/> <property name="unmarshaller"/> <property name="timeout"/> ... </properties> 

I got it, just had to use an intermediate class. Also described in Process NPE in XMLCompositeObjectMappingNodeValue.marshalSingleValue (XMLCompositeObjectMappingNodeValue.java:161)

+7
source share
1 answer

Instead of adapting Map to a List , you should adapt it to an object with the List property.

XmlAdapter (MapPropertiesAdapter)

 import java.util.*; import java.util.Map.Entry; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlAdapter; public class MapPropertiesAdapter extends XmlAdapter<MapPropertiesAdapter.AdaptedProperties, Map<String, String>>{ public static class AdaptedProperties { public List<Property> property = new ArrayList<Property>(); } public static class Property { @XmlAttribute public String name; @XmlValue public String value; } @Override public Map<String, String> unmarshal(AdaptedProperties adaptedProperties) throws Exception { if(null == adaptedProperties) { return null; } Map<String, String> map = new HashMap<String, String>(adaptedProperties.property.size()); for(Property property : adaptedProperties.property) { map.put(property.name, property.value); } return map; } @Override public AdaptedProperties marshal(Map<String, String> map) throws Exception { if(null == map) { return null; } AdaptedProperties adaptedProperties = new AdaptedProperties(); for(Entry<String,String> entry : map.entrySet()) { Property property = new Property(); property.name = entry.getKey(); property.value = entry.getValue(); adaptedProperties.property.add(property); } return adaptedProperties; } } 

Domain Model (root)

The following is a model object with the Map property. The @XmlJavaTypeAdapter annotation @XmlJavaTypeAdapter used to specify the XmlAdapter .

 import java.util.Map; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlJavaTypeAdapter(MapPropertiesAdapter.class) private Map<String, String> properties; } 

Demo

 import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum17024050/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } 

Input.xml / output

 <?xml version="1.0" encoding="UTF-8"?> <root> <properties> <property name="A">a</property> <property name="B">b</property> </properties> </root> 
+8
source

All Articles