Jackson is a great tool for working with JSON in Java. This is a quick tutorial on getting started with serialization and deserialization of JSON documents from and to Java objects. Everything in this post assumes Jackson v2.x.

The Jackson ObjectMapper

ObjectMapper objects are used to serialize and deserialize JSON-formatted strings. You can customize a lot about how the ObjectMapper handles JSON using its configure() methods (allowing single objects in place of lists, whether to print null values, or whether to ignore keys not in the mapping, among other options). You can and should reuse ObjectMapper objects as much as possible for performance reasons; these objects save a lot of information about the Java classes that they are mapping.

The following code creates a static ObjectMapper object that we can use later:

/* Object mapper for serializing and deserializing JSON strings. */
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

Once you have an ObjectMapper object, its very cheap to create ObjectWriter and ObjectReader objects, which are used for serialization and deserialization, respectively. Those will be covered later in this post.

Creating A Class That Is Compatible with Jackson

The JavaBean Approach

Jackson will inspect any class that you pass to it for getters and setters, and use those methods for serialization and deserialization. What follows "get" and "set" in those methods will be used as the key for the JSON field ("intValue" for getIntValue and setIntValue). The following class is an example of this approach:

/* JavaBean class for serialization and deserialization with Jackson. */
public class JacksonBeanExample implements java.io.Serializable {

    /* Set the integer value. Jackson will use this during
     * deserialization. */
    public void setIntValue(final int intValue) {
        this.intValue = intValue;
    }

    /* Get the integer value. Jackson will use this during
     * serialization. */
    public int getIntValue() {
        return this.intValue;
    }

    /* Variable to store an integer value. */
    private int intValue;
}

With this class, we can serialize to JSON using:

/* Serialize a JacksonBeanExample object to a JSON-formatted string. */
JacksonBeanExample jacksonBeanExample = new JacksonBeanExample();
jacksonBeanExample.setIntValue(10);
String serialization = OBJECT_MAPPER.writeValueAsString(jacksonBeanExample);

The result will be that the variable serialization is equal to "{\"intValue\":10}". Similarly, we can deserialize from a JSON-formatted string in the following way:

/* Deserialize a JSON-formatted string to a JacksonBeanExample object. */
ObjectReader objectReader = OBJECT_MAPPER.reader(JacksonBeanExample.class);
JacksonBeanExample jacksonBeanExample =
    objectReader.readValue("{\"intValue\":10}");

After running this code, jacksonBeanExample.getIntValue() will return 10.

Sometimes you may want to use a different name in your getters and setters than appears in the JSON serialization. For example, instead of "intValue", we may want to call the JSON field "value". We can control naming using the @JsonProperty annotation on our getters and setters in the following way:

/* JavaBean class for serialization and deserialization with Jackson. */
public class JacksonBeanExample implements java.io.Serializable {

    /* Set the integer value. Jackson will use this during
     * deserialization. */
    @JsonProperty("value")
    public void setIntValue(final int intValue) {
        this.intValue = intValue;
    }

    /* Get the integer value. Jackson will use this during serialization. */
    @JsonProperty("value")
    public int getIntValue() {
        return this.intValue;
    }

    /* Variable to store an integer value. */
    private int intValue;
}

Now we can expect serialization to yield "{\"value\":10}" and deserialization to work on that same string.

The JsonCreator Approach

What if you don't want your class to follow the JavaBean conventions? For example, you may want to create an immutable class - one without any setters. For those situations we can use the @JsonCreator annotation to declare a method that Jackson uses to create new instances of our class. The example below uses a constructor as the JsonCreator method. Note that you must annotate each argument of the constructor with @JsonProperty and give the name of the JSON field that should be used for that argument.

/* Immutable class for serialization and deserialization with Jackson. */
public final class JacksonImmutableExample implements java.io.Serializable {

    /* Constructor. With the @JsonCreator annotation, Jackson will use this
     * method to generate new JacksonImmutableExample objects. */
    @JsonCreator
    public JacksonImmutableExample(
            @JsonProperty("intValue") final int intValue) {
        this.intValue = intValue;
    }

    /* Get the integer value. Jackson will use this during serialization. */
    public int getIntValue() {
        return this.intValue;
    }

    /* Variable to store an integer value. */
    private final int intValue;
}

Now we can serialize and deserialize in the following ways:

/* Serialize a JacksonImmutableExample object to a JSON-formatted string. */
JacksonImmutableExample jacksonImmutableExample =
    new JacksonImmutableExample(10);
String serialization =
    OBJECT_MAPPER.writeValueAsString(jacksonImmutableExample);

/* Deserialize a JSON-formatted string to a JacksonImmutableExample
 * object. */
ObjectReader objectReader =
    OBJECT_MAPPER.reader(JacksonImmutableExample.class);
JacksonImmutableExample jacksonImmutableExample =
    objectReader.readValue("{\"intValue\":10}");

Summary

Of course there is a lot more that Jackson can do, but this should be enough to get started with mapping JSON documents to Java objects.

Comment