3

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.)

2 Answers 2

1

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;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Emi You are right. For me this is sufficient. (But it may be extended to work this other objects with a usable string-representation.)
1

The NamedMapConverter can achieve this. Take a look at http://x-stream.github.io/javadoc/com/thoughtworks/xstream/converters/extended/NamedMapConverter.html

The third example shows exactly that, what you want:

    new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, "value", Integer.class, true, true, xstream.getConverterLookup());

Creates this xml output:

    <map>
        <entry key="keyValue" value="0"/>
    </map>

3 Comments

Thanks for your answer. Unfortunately this is not what I need. I need a resulting xml like <entity keyvalue="value">, so the key of the map-entry should be the name of the xml-attribute.
Oh sorry, in this case I think the only way is to extend MapConverter
You took the XML output example from your provided link. However, the XML is still not valid. Would be valid, if you remove the '>' sign after "entry"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.