5

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.

Community
  • 1
  • 1
Matt
  • 3,422
  • 1
  • 23
  • 28
  • Hi, Even I am doing something similar but bit different. I have few dedicated fields and then whatever is extra those things I would like to store in `Map` but due to some reason all the values are being moved to `Map`. I have created a question here if you get a chance can you please have a look and provide your explanation?https://stackoverflow.com/questions/67648941/jaxb-moxy-unmarshalling-assigns-all-field-values-to-mapstring-object-rather-th – BATMAN_2008 May 22 '21 at 11:28

1 Answers1

1

@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:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thx Blaise, it doesn't seem to work. I get the following output : . I'm using the last stable version of MOXy (2.5.1) – Matt Jan 03 '14 at 09:09
  • My bad, I didn't declare Moxy as the JAXB implementation the right way. I've now put the jaxb.properties in the same package as my annotated classes and it works better. I still have a name space problem, my XML output now looks like this : VALUE_1, which is good except for the xmlns attribute. Any idea? – Matt Jan 03 '14 at 11:00
  • I tried the approach mentioned here along with the other fields but for some reason due to the `@XmlPath(".")` all the fields would be moved into `map`. I have few additional fields along with `Map` and I expect those fields to be unmarshalled directly to the respective field names and only unknown fields to be mapped to `Map` but for some reason all fields are moved within the `Map` which is not expected. Can you please provide some more explanation. – BATMAN_2008 May 22 '21 at 10:53
  • I have created a question for it. If possible can you please have a look and provide your suggestion: https://stackoverflow.com/questions/67648941/jaxb-moxy-unmarshalling-assigns-all-field-values-to-mapstring-object-rather-th – BATMAN_2008 May 22 '21 at 11:26