JAXB is a very efficient framework to covert XML to Object and Object to XML in Java. In this tutorial, we are going to see how to convert Java Map to XML using JAXB.

JAXB Map to XML Conversion:

Add the below jaxb-api dependency in pom.xml

pom.xml
<dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.1</version>
</dependency>
Note: Java 1.9+ users have to use the below dependencies to get the jaxb-api, you can follow this StackOverflow thread for complete details.
java-1.9+ pom.xml
<!-- API, java.xml.bind module -->
       <dependency>
           <groupId>jakarta.xml.bind</groupId>
           <artifactId>jakarta.xml.bind-api</artifactId>
           <version>2.3.2</version>
       </dependency>

       <!-- Runtime, com.sun.xml.bind module -->
       <dependency>
           <groupId>org.glassfish.jaxb</groupId>
           <artifactId>jaxb-runtime</artifactId>
           <version>2.3.2</version>
       </dependency>

We can not convert the Java Map directly to XML because JAXB expects a @XmlRootElement annotation on top of the entity class to convert into XML. If you try to convert the Map object you would get the below exception.

Exception in thread “main” 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:563)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:452)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:298)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:226)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:80)

The Exception clearly saying @XmlRootElement is mandatory for JAXBContext.

So to fix the issue we can create a Wrapper for the HashMap class by defining the @XmlRootElement annotation on top of the Wrapper class. Let’s see in practice.

Java Map to XML Conversion Example:

In this example, I am going to create a map with a list of items, where a category is a key and the list of items are value.

So basically I need two wrapper classes to define my use-case: one is for List and another is for Map.

Creating ItemsList wrapper class to hold the items.

ItemsList.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;

@XmlRootElement(name = "item")
@XmlAccessorType(XmlAccessType.FIELD)
public class ItemsList {
    private List<Item> item = new ArrayList<>();

    public List<Item> getItem() {
        return item;
    }
    
    public void setItem(List<Item> itemsList) {
        this.item = item;
    }
}

Create an ItemsMap class to hold the list of items by category.

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

@XmlRootElement(name = "items")
@XmlAccessorType(XmlAccessType.FIELD)
public class ItemsMap {

    private Map<String, ItemsList> itemsMap = new HashMap<>();

    public Map<String, ItemsList> getItemsMap() {
        return itemsMap;
    }

    public void setItemsMap(Map<String, ItemsList> itemsMap) {
        this.itemsMap = itemsMap;
    }
}

Now the wrapper classes are ready to use. Now let’s prepare the list of items, make it as a map and convert the map into XML.

MapToXML.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

public class MapToXML {
    public static void main(String[] args) throws JAXBException {
        // Creating HashMap to hold ItemsList (Wrapper for List)
        HashMap<String, ItemsList> map = new HashMap<>();
        map.put("electronics",getElecrtonics());
        map.put("books",getBooks());
    
        // Setting map to ItemsMap (Wrapper for HashMap)
        ItemsMap iMap = new ItemsMap();
        iMap.setItemsMap(map);

        JAXBContext jaxbContext = JAXBContext.newInstance(ItemsMap.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        // marshalling ItemsMap.
        jaxbMarshaller.marshal(iMap, System.out);
    }

    // Building the Electronic items
    public static ItemsList getElecrtonics(){
        ArrayList<Item> list = new ArrayList<Item>(Arrays.asList(new Item(100,"Samsung",15000.00),
                new Item(200,"iPhone10",110000.00)));
        ItemsList itemsList = new ItemsList();
        itemsList.getItem().addAll(list);
        return itemsList;
    }
    // Building the Book items
    public static ItemsList getBooks(){
        ArrayList<Item> list = new ArrayList<Item>(Arrays.asList(new Item(2000,"Core Java",500.00),
                new Item(3000,"Spring in Action",750.00)));
        ItemsList itemsList = new ItemsList();
        itemsList.getItem().addAll(list);
        return itemsList;
    }
}

Output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
    <itemsMap>
        <entry>
            <key>electronics</key>
            <value>
                <item>
                    <itemId>100</itemId>
                    <itemName>Samsung</itemName>
                    <price>15000.0</price>
                </item>
                <item>
                    <itemId>200</itemId>
                    <itemName>iPhone10</itemName>
                    <price>110000.0</price>
                </item>
            </value>
        </entry>
        <entry>
            <key>books</key>
            <value>
                <item>
                    <itemId>2000</itemId>
                    <itemName>Core Java</itemName>
                    <price>500.0</price>
                </item>
                <item>
                    <itemId>3000</itemId>
                    <itemName>Spring in Action</itemName>
                    <price>750.0</price>
                </item>
            </value>
        </entry>
    </itemsMap>
</items>

Done!

References:

Happy Learning 🙂