Serializing POJOs with Jackson

Jackson's sensible defaults allow developers to skip all configuration in many cases by simply defining classes responsible for serialization. I covered custom serializers with Jackson before, but it is often less effort to avoid custom serializers than create custom serializers. In addition, extending core classes of a library tightly couple an application to that library. That coupling cost may be worth paying, but if it can be avoided easily, why not avoid it?


Jackson has great POJO binding out of the box, which makes serialization a lot simpler by defining classes that are dedicated to writing out and reading in JSON. Consider a locomotive JSON document that looks like this:

  "manufacturer": "Baldwin Locomotive Works",
  "year": 1909,
  "owner": "Southern Pacific Railroad",
  "serialNumber": 29064,
  "type": {
    "notation": "2-8-0",
    "name": "Consolidation"

This locomotive document would require two POJOs for Jackson's serialization:

package net.sghill.examples.serialization;

public class Locomotive {
    private String manufacturer;
    private Integer year;
    private String owner;
    private Integer serialNumber;
    private Type type;

    public String getManufacturer() { return manufacturer; }
    public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; }
    public Integer getYear() { return year; }
    public void setYear(Integer year) { this.year = year; }
    public String getOwner() { return owner; }
    public void setOwner(String owner) { this.owner = owner; }
    public Integer getSerialNumber() { return serialNumber; }
    public void setSerialNumber(Integer serialNumber) { this.serialNumber = serialNumber; }
    public Type getType() { return type; }
    public void setType(Type type) { this.type = type; }
package net.sghill.examples.serialization;

public class Type {
    private String name;
    private String notation;

    public String getName() { return name; }
    public void setName(String name) { = name; }
    public String getNotation() { return notation; }
    public void setNotation(String notation) { this.notation = notation; }

The getters and setters are important here, not the fields. A JSON key of “name” matches up with setName and getName. Jackson automatically strips off the get or set and downcases the first letter of the remaining word. A few quick examples should help make the JavaBean conventions clear:

| JSON key           | expected getter       | expected setter                |
| name               | getName()             | setName(String n)              |
| locomotiveNumber   | getLocomotiveNumber() | setLocomotiveNumber(Integer n) |
| flag               | isFlag()              | setFlag(boolean f)             |

Data Types

It's worth the effort to keep these classes simple. On my projects we've tried hard to ensure the serialization objects only have fields with types from java.lang.* or other serialization classes. Jackson already knows how to serialize these types, so sticking to them makes life easy. By avoiding complex types like java.util.Date, there is no more guessing how that should be serialized (millis? ISO 8601?). Instead, define that formatting behavior somewhere easily testable - like a POJO for mapping between domain objects and serialization objects.


When using a library or framework that provides Jackson integration out of the box (like Dropwizard, Spring, or Retrofit) we don't have to deal with an ObjectMapper directly. Still, it is often helpful to know how to serialize and deserialize on your own. Using ObjectMapper is straightforward:

// to JSON
String json = new ObjectMapper().writeValueAsString(myLocomotive);

// from JSON
Locomotive l = new ObjectMapper().readValue(myJsonString, Locomotive.class);

The default ObjectMapper assumes the JSON it is reading and writing will be camelCase. It's a good default because that's pretty much always what we want, but there are cases where we need to consume a PascalCase API or write out a snake_case response. For concerns like these, the ObjectMapper can be configured and supplied to the library or framework that needs it. For example, here is how you configure an ObjectMapper to always use snake_case:

new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy);


  • The namespaces here are for Jackson 2.0+. Jackson 1.9 can co-exist with 2.0 because everything is provided in a different package.
  • Serialization objects have gone by many different names on my teams:
    • WireTypes
    • Representations
    • Resources
    • Responses

How Do I Make Cross-Platform File Paths in Java?

It’s a lot easier to deploy your Java application cross-platform if you consider a few small details like file paths first.

Read More

5-Minute Intro to Gradle

A quick and painless introduction to setting up a gradle project with dependencies in IntelliJ IDEA.

Read More

How Do I Migrate My Gradle Dependencies To Be Transitive?

Lessons learned from a migration to gradle that explicitly defined every single dependency, transitive or not, and how we got to transitive dependencies.

Read More

Creeping Inconsistencies

Inconsistencies slowly creep into codebases. The cost of inconsistency becomes very clear when a new team member is onboarding. This article covers the subtle ways our JavaScript diverged over time, and how one person being aggressive in aligning styles worked well for us.

Read More

How Do I Write a Jackson JSON Serializer & Deserializer?

Getting started with Jackson in Java could be more straightfoward. This article shows one way to serialize a class with a custom serializer.

Read More

Backbone.js, Underscore.js, and Sprockets 1.0.x Concatenation

A [now outdated] look at how to tie together javascript libraries like backbone and underscore with the original sprockets.

Read More

DRYing Views: Tables, Partials, and Helpers

A super detailed look at the how to DRY up some views in Rails. Walks through the actual code of ExpenseLynx, an open source expense system I built for my last course at Loyola University Chicago.

Read More