Search code examples
javaxmldictionaryxstream

How to map an Hashmap to key-value-attributes in XML using xstream


I have the following entity:

@XStreamAlias("entity")
public class MapTestEntity {

    @XStreamAsAttribute
    public Map<String, String> myMap = new HashMap<>();

    @XStreamAsAttribute
    public String myText;
}

I use it with xstream like:

MapTestEntity e = new MapTestEntity();
e.myText = "Foo";
e.myMap.put("firstname", "homer");
e.myMap.put("lastname", "simpson");

XStream xstream = new XStream(new PureJavaReflectionProvider());
xstream.processAnnotations(MapTestEntity.class);
System.out.println(xstream.toXML(e));

and get the following xml:

<entity myText="Foo">
  <myMap>
    <entry>
      <string>lastname</string>
      <string>simpson</string>
    </entry>
    <entry>
      <string>firstname</string>
      <string>homer</string>
    </entry>
  </myMap>
</entity>

But I need to map the HashMap to attributes in xml like:

<entity myText="Foo" lastname="simpson" firstname="homer" />

How can I do that with XStream? Can I use a custom converter or mapper or something like that? TIA!!

(Of course my code needs to be ensure that are no duplicates in xml attributes.)


Solution

  • I wrote an own Converter:

    public class MapToAttributesConverter implements Converter {
    
        public MapToAttributesConverter() {
        }
    
        @Override
        public boolean canConvert(Class type) {
            return Map.class.isAssignableFrom(type);
        }
    
        @Override
        public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
            Map<String, String> map = (Map<String, String>) source;
            for (Map.Entry<String, String> entry : map.entrySet()) {
                writer.addAttribute(entry.getKey(), entry.getValue().toString());
            }
        }
    
        @Override
        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Map<String, String> map = new HashMap<String, String>();
            for (int i = 0; i < reader.getAttributeCount(); i++) {
                String key = reader.getAttributeName(i);
                String value = reader.getAttribute(key);
                map.put(key, value);
            }
            return map;
        }
    }