How to deserialize xml into a map of custom attributes (and their values) using SimpleXml?

I am using SimpleXml .

xml I deserialize looks something like this:

<?xml version="1.0" encoding="UTF-8"?> 
<test a="1" e="2" f="5"/>


What attributes are a

, e

and f

it is not known at runtime - can also be q

and z


Class definition:

@Root (strict = false)
public class Test {
   @ElementMap (entry = "test", attribute = true)
   public HashMap<String, Integer> map;


I expect it

will contain "a" -> 1

, "b" -> 2

and "f" -> 5

after deserialization.

Instead, I keep getting the exception: unnable to satisfy @org.simpleframework.xml.ElementMap ... on field 'map' ... for class Test ...

(fluff removed - the exception message doesn't provide any further clarification).

I've tried tinkering with various attributes ElementMap

(attachment, not attachment, etc.) but nothing worked so far.

(These values ​​are actually numeric, although this is indirect, and I'd be good with string values ​​to parse them myself if necessary, but I'm not sure if that matters at all.)

What solution?

And if SimpleXml

doesn't suggest any out of the box, what's the suggested workaround?


source to share

1 answer

I solved it with Converter , which allows manual deserialization.

So now the model:

public class Test {
   @Convert (MapConverter.class)
   @Element (name = "test")
   public HashMap<String, Integer> test;


And MapConverter


public class MapConverter implements Converter<HashMap<String, Integer>> {
   public HashMap<String, Integer> read(InputNode inputNode) throws Exception {
      final HashMap<String, Integer> result = new HashMap<String, Integer>();

      for (final String attributeName : inputNode.getAttributes()) {
         final String value = inputNode.getAttribute(attributeName).getValue();
         result.put(attributeName, Integer.parseInt(value));

      return result;

   public void write(OutputNode outputNode, HashMap<String, Integer> stringIntegerHashMap)
         throws Exception {
      // not used


Note that for this you need to pass an instance AnnotationStrategy

to Persister


// instead of new Persister()
Persister persister = new Persister(new AnnotationStrategy()); 


I am not so keen on this solution because

  • I suspect this might be overkill.

  • The initialization Persister

    is done deep inside an existing library that I have to use, so I had to open up the code for it to work at all.

The fact that it Persister

ignores one of the default built-in struct annotations causes a confusing API (although this behavior is documented). But that's a different story.

I wonder if someone came up with something better.



All Articles