I have a class world that contains a map of humans. If I marshal the class world I get following output:
&l
My solution
I added the key attribute to human and then I converted the map to an array:
@XmlRootElement
public class World {
@XmlJavaTypeAdapter(HumanAdapter.class)
private Map<String, Human> humans = new HashMap<String, Human>();
public World(){}
}
public class Human {
@XmlElement
private String name;
@XmlAttribute(name="key")
private String key;
public Human(){}
}
public class HumanAdapter extends XmlAdapter<HumanJaxbCrutch, Map<String, Human>> {
@Override
public HumanJaxbCrutch marshal(Map<String, Human> humans) throws Exception {
List<Human> list = new ArrayList<Human>();
for (Entry<String, Human> entry : humans.entrySet()) {
list.add(entry.getValue());
}
HumanJaxbCrutch humanJaxbCrutch = new HumanJaxbCrutch();
humanJaxbCrutch.setCourses(list.toArray(new Human[list.size()]));
return humanJaxbCrutch;
}
@Override
public Map<String, Human> unmarshal(HumanJaxbCrutch humans) throws Exception {
Map<String, Human> map = new HashMap<String, Human>();
for(Human human : humans.getCourses()){
map.put(human.getKey(), human);
}
return map;
}
}
class HumanJaxbCrutch {
private Human[] courses;
@XmlElement(name = "human")
public Human[] getCourses() {
return courses;
}
public void setCourses(Human[] courses) {
this.courses = courses;
}
}
As was pointed out by ilcavero an XmlAdapter
can be used to apply an alternative mapping to Map (or any type) in JAXB. Below is a link to a concrete example:
For More Information
I think you are looking for the XmlValue annotation : http://jaxb.java.net/tutorial/section_6_2_7_4-Mapping-a-Class-to-Simple-Content-or-Simple-Type-XmlValue.html#Mapping%20a%20Class%20to%20Simple%20Content%20or%20Simple%20Type:%20XmlValue
In your case it would be applied to HumanEntry.value instead of XmlElement