I'm using the JAXB implementation that comes with J2SE to serialize a bean that contains a HashMap property. I would assume that this should work out of the box since this states
JAXB spec defines a special handling for Map when it's used as a propety of a bean. For example, the following bean would produce XMLs like the following: ...
This more or less works unless the structure has more than one level, i.e. the HashMap is a property of a bean that is a property of a bean - like this:
import java.util.HashMap;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.JAXB;
class bean {
@XmlElement public HashMap<String,String> map;
}
@XmlRootElement class b2 {
@XmlElement public bean b;
}
class foo {
public static void main(String args[]) {
try {
bean b = new bean();
b.map = new HashMap<String,String>();
b.map.put("a","b");
b2 two = new b2();
two.b=b;
JAXB.marshal(two, System.out);
} catch (Exception e) {
System.out.println("Exception: " + e.toString());
}
}
}
This outputs
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><b2><b><map/></b></b2>
instead of a correctly formatted HashMap. It works if I annotate bean
with @XmlRootElement
and remove the @XmlElement
from map
, but I don't see why that should be necessary. Is it supposed to be like that?
The explanation is given on the website you linked:
Unfortunately, as of 2.1, this processing is only defined for bean properties and not when you marshal HashMap as a top-level object (such as a value in JAXBElement.) In such case, HashMap will be treated as a Java bean, and when you look at HashMap as a bean it defines no getter/setter property pair, so the following code would produce the following XML:
Bean with Map:
m = new HashMap();
m.put("abc",1);
marshaller.marshal(new JAXBElement(new QName("root"),HashMap.class,m),System.out);
XML representation:
<root />
This issue has been recorded as #223 and the fix needs to happen in later versions of the JAXB spec.