Search code examples
javaxmljaxbmarshalling

How to change default Hashmap tag name from <entry> to something else when marshalling XML using JAXB?


I am attempting to change the value of the tag in the marshalled XML using JAXB to . My clients that are calling my application are expecting , previously I was using XSLT to do this transformation but I am switching to a JAXB approach to create the XML response.

Right now this is the error XML that I am creating:

<error>
    <details>
        <entry>
            <key>code</key>
            <value>1234</value>
        </entry>
        <entry>
            <key>customKey</key>
            <value>customerValue</value>
        </entry>
    </details>
</error>

And I need it to look like this:

<error>
    <details>
        <detail>
            <key>code</key>
            <value>1234</value>
        </detail>
        <detail>
            <key>customKey</key>
            <value>customerValue</value>
        </detail>
    </details>
</error>

The Java object that I am using to marshall is as follows:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Map;

@XmlRootElement(
        name = "error"
)
@XmlAccessorType(XmlAccessType.FIELD)
public class Error {
    
    private Map<String, String> details;

    public Error() {

    }

    public Error(Map<String, String> details) {
        this.details = details;
    }
    
    public Map<String, String> getDetails() {
        return details;
    }

    public void setDetails(Map<String, String> details) {
        this.details = details;
    }
}

Is there a way to change the default naming convention when marshalling a Map to XML using JAXB? Is there possibly I can do this another way with nested objects instead of a hash map?

I was messing around attempting to do a List of <details> but my JAXB was having troubles marshalling a list.

Thank you


Solution

  • Is there a way to change the default naming convention when marshalling a Map to XML using JAXB?

    I think there is no way to change this naming, because the element names of <entry>, <key> and <value> are hard-coded in the JAXB implementation.
    In class com.sun.xml.bind.v2.runtime.property.SingleMapNodeProperty (which is responsible for serializing a Map entry) there is actually this code:

    this.entryTag = context.nameBuilder.createElementName("","entry");
    this.keyTag = context.nameBuilder.createElementName("","key");
    this.valueTag = context.nameBuilder.createElementName("","value");
    

    Is there possibly I can do this another way with nested objects instead of a hash map?

    I was messing around attempting to do a List of <details> but my JAXB was having troubles marshalling a list.

    I don't know which troubles you encountered. But you can achieve your goal just by changing in your Error class from

    private Map<String, String> details;
    

    to

    @XmlElementWrapper(name = "details")
    @XmlElement(name = "detail")
    private List<Detail> details;
    

    (and of course also adapting the constructor/getter/setter accordingly).
    You will also need a Detail class for representing the content within <detail>...</detail>.

    @XmlAccessorType(XmlAccessType.FIELD)
    public class Detail {
    
        @XmlElement
        private String key;
    
        @XmlElement
        private String value;
        
        // constructors, getters, setters (omitted here for brevity)
    }