Matt
Matt

Reputation: 3662

HashMap JAXB mapping using @XmlAnyElement

I'm trying to realize an XML mapping involving an HashMap. Here is my use case : I want to get this :

<userParameters>
    <KEY_1>VALUE_1</KEY_1>
    <KEY_2>VALUE_2</KEY_2>
    <KEY_3>VALUE_3</KEY_3>
</userParameters>

My UserParameters class looks like this :

@XmlRootElement
public class UserParameters {

    private final Map<QName, String> params = new HashMap<>();

    @XmlAnyElement
    public Map<QName, String> getParams() {
        return params;
    }

}

I get the following error while marshalling :

Caused by: javax.xml.bind.JAXBException: class java.util.HashMap nor any of its super class is known to this context.
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:593)
    at com.sun.xml.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:109)
    ... 54 more

It works fine with @XmlAnyAttribute and I get : <userParameters KEY_1="VALUE_1" ... />

From the answers I saw, it seems like I have to make my own XmlAdapter but it feels like overkill for such a simple and common need.

--- UPDATE ---

I found a promising solution here : JAXB HashMap unmappable

The only inconvenient is that it seems to mess up the namespaces.

Here is my new UserParameters class :

@XmlAnyElement
public List<JAXBElement> getParams() {
    return params;
}

public void addParam(String key, String value) {
    JAXBElement<String> element = new JAXBElement<>(new QName(key), String.class, value);
    this.params.add(element);
}

And here is what I get in my XML output :

<params:userParameters>
    <KEY_1 xmlns="" xmlns:ns5="http://url.com/wsdl">
        VALUE_1
    </KEY_1>
</params:userParameters>

I have no idea why JAXB is declaring a namespace in the KEY_1 element.

Upvotes: 5

Views: 3262

Answers (1)

bdoughan
bdoughan

Reputation: 149007

@XmlAnyAttribute vs @XmlAnyElement

With attributes it is clear that the map key is the attribute name and that the map value is the attribute value. With elements it is not so clear, the map key could be the element name, but what is the value the entire element? What happens if the key and the value don't match.

Mapping this Use Case

You need to use an XmlAdapter for this use case. Below is an example of how it can be done using EclipseLink JAXB (MOXy), I'm the MOXy lead:

Upvotes: 1

Related Questions