Convert XML to JSON Using Jackson

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.11.1</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.11.1</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.

Related posts:

Biểu thức Lambda trong Java 8 – Lambda Expressions
Creating a Generic Array in Java
Java Program to Implement LinkedHashMap API
Getting Started with Stream Processing with Spring Cloud Data Flow
Hướng dẫn Java Design Pattern – Flyweight
Java Program to Solve any Linear Equation in One Variable
Converting between an Array and a List in Java
Tìm hiểu cơ chế Lazy Evaluation của Stream trong Java 8
Guide to BufferedReader
Java Program to Implement Sorting of Less than 100 Numbers in O(n) Complexity
Java Program to Implement Knight’s Tour Problem
Jackson – Change Name of Field
The Order of Tests in JUnit
Map to String Conversion in Java
Guide to java.util.concurrent.BlockingQueue
Java Program to Implement Interpolation Search Algorithm
Bootstrapping Hibernate 5 with Spring
Format ZonedDateTime to String
Java Program to Give an Implementation of the Traditional Chinese Postman Problem
Limiting Query Results with JPA and Spring Data JPA
HttpClient 4 – Follow Redirects for POST
Java Program to Find kth Largest Element in a Sequence
Java – Reader to Byte Array
How to Delay Code Execution in Java
Spring REST API + OAuth2 + Angular (using the Spring Security OAuth legacy stack)
Java program to Implement Tree Set
Java – Combine Multiple Collections
Quick Guide to Spring MVC with Velocity
Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions
Từ khóa static và final trong java
Sử dụng CyclicBarrier trong Java
Rest Web service: Filter và Interceptor với Jersey 2.x (P2)