dtchmnt
dtchmnt

Reputation: 15

JaxB Marshalling of a Key, Value Pair, where Value can be another Key, Value pair

I have this Object, as a node of a complex Object:

public class Parameter implements Serializable {

@XmlElement(name = "Key")
protected String key;
@XmlElement(name = "Value")
protected Object value;

}

The propety "Value" can either be a String, effectively making the Parameter a Map<String, String>, or it can be another Parameter Value. I have a List of these Objects.

for Example, both below XML snippets are valid:

<Parameter>
<Key>MyKey</Key>
<Value>MyValue</MyValue>
</Parameter>

<Parameter>
<Key>Key1</Key>
<Value>
    <Key>Key2</Key>
    <Value>
        <Key>Key3</Key>
        <Value>ValueInString1</Value>
    </Value>
    <Value>
        <Key>Key4</Key>
        <Value>ValueInString2</Value>
    </Value>
</Value>

What I am looking for is a way of implementing an XMLAdapter that can handle this. The 2 main ideas are:

  1. Use the Adapter for the whole parameter Class.
  2. Use the Adapter only for the "Value" Property.

Idea #1 stucks on how to marshal a list of key value pairs Idea #2 stucks on, if the value is a Parameter, how to invoke the Generic Marshaller for Parameter.class

Upvotes: 0

Views: 53

Answers (2)

dtchmnt
dtchmnt

Reputation: 15

Just for reference:

  • JaxB marshalling could not do that.
  • Jackson could do that

I ended up removing the JaxB Annotations, so that Jackson can parse and print the response required

Upvotes: 0

Joel Victor
Joel Victor

Reputation: 161

You can use a MapAdapter that converts the Map to an array of MapElements as follows:

class MapElements {
    @XmlAttribute
    public String key;
    @XmlAttribute
    public String value;

    private MapElements() {
    } //Required by JAXB

    public MapElements(String key, String value) {
        this.key = key;
        this.value = value;
    }
}
public class MapAdapter extends XmlAdapter<MapElements[], Map<String, String>> {
    public MapAdapter() {
    }

    public MapElements[] marshal(Map<String, String> arg0) throws Exception {
        MapElements[] mapElements = new MapElements[arg0.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : arg0.entrySet())
            mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());

        return mapElements;
    }

    public Map<String, String> unmarshal(MapElements[] arg0) throws Exception {
        Map<String, String> r = new TreeMap<String, String>();
        for (MapElements mapelement : arg0)
            r.put(mapelement.key, mapelement.value);
        return r;
    }
}

Upvotes: 0

Related Questions