1. Overview
In this tutorial, we’ll see how to convert an XML message to JSON using Jackson.
For readers new to Jackson, consider getting familiar with the basics first.
2. An Introduction to Jackson
We can think about parsing JSON in three different ways with Jackson:
- The first and most common is data binding with ObjectMapper
- The second is mapping to a tree data structure with TreeTraversingParser and JsonNode
- And the third is streaming the tree data structure by token, using JsonParser and JsonGenerator
Now, Jackson also supports the first two for XML data. As such, let’s see how Jackson can help us do the conversion from one format to the other.
3. Dependencies
First, we need to add the jackson-databind dependency to our pom.xml:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.7</version> </dependency>
This library is going to allow us to use the data binding API.
The second is jackson-dataformat-xml which adds Jackson’s XML support:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.7</version> </dependency>
4. Data Binding
Data binding, simply put, is when we want to map serialized data directly to a Java object.
To explore this, let’s define our XML with Flower and Color properties:
<Flower> <name>Poppy</name> <color>RED</color> <petals>9</petals> </Flower>
This is similar to this Java notation:
public class Flower { private String name; private Color color; private Integer petals; // getters and setters } public enum Color { PINK, BLUE, YELLOW, RED; }
Our first step will be to parse the XML into a Flower instance. To do that, let’s create an instance of XmlMapper, Jackson’s XML equivalent for ObjectMapper and use its readValue method:
XmlMapper xmlMapper = new XmlMapper(); Flower poppy = xmlMapper.readValue(xml, Flower.class);
Once we have our Flower instance, we’ll want to write it out as JSON using the familiar ObjectMapper:
ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(poppy);
And, as a result, we get our JSON equivalent:
{ "name":"Poppy", "color":"RED", "petals":9 }
5. Tree Traversal
At times, looking directly at the tree structure can offer more flexibility, like in the case that we don’t want to maintain an intermediary class or we only want to convert a portion of the structure.
Though, as we’ll see, it comes with some tradeoffs.
The first step is similar to our first step when we use data binding. This time, though, we’ll use the readTree method:
XmlMapper xmlMapper = new XmlMapper(); JsonNode node = xmlMapper.readTree(xml.getBytes());
Having done this, we’ll have a JsonNode which has 3 children, as we expected: name, color, and petals.
Then, we can again use ObjectMapper, just sending our JsonNode instead:
ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(node);
Now, the outcome is slightly different compared to our last example:
{ "name":"Poppy", "color":"RED", "petals":"9" }
Upon careful inspection, we can see that the petals attribute is serialized into a string instead of a number! This is because readTree doesn’t infer the datatype without an explicit definition.
5.1. Limitations
And, there are certain limitations with Jackson’s XML tree traversal support:
- Jackson cannot differentiate between an Object and an Array. Since XML lacks native structures to distinguish an object from a list of objects, Jackson will simply collate repeated elements into a single value.
- And, since Jackson wants to map each XML element to a JSON node, it doesn’t support mixed content.
For these reasons, the official Jackson docs recommend against using Tree models to parse XML.
6. Memory Constraints
Now, both of these have the notable downside that the entire XML needs to be in memory at once in order to perform the conversion. Until Jackson supports streaming the tree structure as tokens, we’ll be stuck with this constraint or we’ll need to take a look at rolling our own with something like XMLStreamReader.
7. Conclusion
In this tutorial, we briefly learned different ways in which Jackson can read XML data and write it to JSON. Also, we took a quick look at the limitations of each supported approach.
As usual, the full source code that accompanies the tutorial is available over on GitHub.