I have a Map<String, String>
.
The first idea everyone has is to convert it to a List<Pair<String,String>>
(Pair
being a custom class).
I've tried a @XmlAdapter
like this:
public class MapPropertiesAdapter extends XmlAdapter<List<Property>, Map<String,String>> { ... }
But Eclipse MOXy, the JAXB impl I use, ended up with a ClassCastException
- "can't convert HashMap to Collection".
Is this conversion supported by JAXB? Or did I overlook some documentation part which explains why it isn't?
PS: I wanted to get XML like this:
<properties>
<property name="protocol"/>
<property name="marshaller"/>
<property name="unmarshaller"/>
<property name="timeout"/>
...
</properties>
I got it, only had to use an intermediate class. Also described at Handle NPE in XMLCompositeObjectMappingNodeValue.marshalSingleValue( XMLCompositeObjectMappingNodeValue.java:161)
JAXB_FORMATTED_OUTPUT. The name of the property used to specify whether or not the marshalled XML data is formatted with linefeeds and indentation. static String.
In the Java-related RFC 2713, marshalling is used when serialising objects for remote invocation. An object that is marshalled records the state of the original object and it contains the codebase (codebase here refers to a list of URLs where the object code can be loaded from, and not source code).
This abstract class defines methods for adapting a bound type to a value type or vice versa. The methods are invoked by the JAXB binding framework during marshaling and unmarshalling: XmlAdapter.
Marshalling – Converting Java Object to XML Marshalling gives a client application the ability to convert a JAXB-derived Java object tree into XML data. By default, the Marshaller uses UTF-8 encoding when generating XML data. Next, we will generate XML files from Java objects.
Instead of adapting the Map
to a List
, you should adapt it to an object that has a 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)
Below is a model object with a Map
property. The @XmlJavaTypeAdapter
annotation is 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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With