Search code examples
javaxmljaxbjaxb2

JAXB: how to marshall map into <key>value</key>


The question is about JAXB Map marshalling - there is plenty of examples on how to marhsall a Map into a structure like follows:

<map>
  <entry>
    <key> KEY </key>
    <value> VALUE </value>
  </entry>
  <entry>
    <key> KEY2 </key>
    <value> VALUE2 </value>
  </entry>
  <entry>
  ...
</map>

In fact, this is natively supported by JAXB. What I need, however, is the XML where key is the element name, and value is its content:

<map>
  <key> VALUE </key>
  <key2> VALUE2 </key2>
 ...
</map>

I didn't succeed implementing my Map adapter the way it is recommended by JAXB developers (https://jaxb.dev.java.net/guide/Mapping_your_favorite_class.html), as I need, he - dynamic attribute name :)

Is there any solution for that?

P.S. Currently I have to create a dedicated container class for each typical set of key-value pairs I want to marshall to XML - it works, but I have to create way too many of these helper containers.


Solution

  • the code provided didn't work for me. I found another way to Map :

    MapElements :

    package com.cellfish.mediadb.rest.lucene;
    
    import javax.xml.bind.annotation.XmlElement;
    
    class MapElements
    {
      @XmlElement public String  key;
      @XmlElement public Integer value;
    
      private MapElements() {} //Required by JAXB
    
      public MapElements(String key, Integer value)
      {
        this.key   = key;
        this.value = value;
      }
    }
    

    MapAdapter :

    import java.util.HashMap;
    import java.util.Map;
    
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    class MapAdapter extends XmlAdapter<MapElements[], Map<String, Integer>> {
        public MapElements[] marshal(Map<String, Integer> arg0) throws Exception {
            MapElements[] mapElements = new MapElements[arg0.size()];
            int i = 0;
            for (Map.Entry<String, Integer> entry : arg0.entrySet())
                mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());
    
            return mapElements;
        }
    
        public Map<String, Integer> unmarshal(MapElements[] arg0) throws Exception {
            Map<String, Integer> r = new HashMap<String, Integer>();
            for (MapElements mapelement : arg0)
                r.put(mapelement.key, mapelement.value);
            return r;
        }
    }
    

    The rootElement :

    import java.util.HashMap;
    import java.util.Map;
    
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlRootElement
    public class Root {
    
        private Map<String, Integer> mapProperty;
    
        public Root() {
            mapProperty = new HashMap<String, Integer>();
        }
    
        @XmlJavaTypeAdapter(MapAdapter.class)
        public Map<String, Integer> getMapProperty() {
            return mapProperty;
        }
    
        public void setMapProperty(Map<String, Integer> map) {
            this.mapProperty = map;
        }
    
    }
    

    I found the code in this website : http://www.developpez.net/forums/d972324/java/general-java/xml/hashmap-jaxb/