How Do I Write a Jackson JSON Serializer & Deserializer?

Update (12/22/2015) Considering writing serialization classes instead? Check out Serializing POJOs with Jackson.

Jackson is a great JSON serialization library for Java. Finding out how to write serializers and deserializers can be frustrating, in no small part thanks to the enormous API Jackson comes with.

Note The following is known to work with Jackson 1.8.5, which ships with RESTEasy 2.3.2.Final.

Assume we have a naive User class we’re interested in writing the Serializer and Deserializer for. Not much is notable here, except for the annotations that tell Jackson who knows how to serialize and deserialize this class.

package net.sghill.example;

import net.sghill.example.UserDeserializer;
import net.sghill.example.UserSerializer;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;

@JsonDeserialize(using = UserDeserializer.class)
@JsonSerialize(using = UserSerializer.class)
public class User {
    private ObjectId id;
    private String   username;
    private String   password;
    public User(ObjectId id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public ObjectId getId()       { return id; }
    public String   getUsername() { return username; }
    public String   getPassword() { return password; }
}

Deserialization

We’ll go about creating our deserializer by extending Jackson’s abstract JsonDeserializer class, and giving it the type we want to deserialize to. Maybe most difficult is figuring out that you can reference the JSON by field name with the JsonParser‘s ObjectCodec.

package net.sghill.example;

import net.sghill.example.User;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.ObjectCodec;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import java.io.IOException;

public class UserDeserializer extends JsonDeserializer {
    @Override
    public User deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        return new User(null,
                node.get("username").getTextValue(),
                node.get("password").getTextValue());
    }
}

Serialization

The serialization of the id and password will never be beneficial, and all we want is an object that contains the username.

Mirroring above, we’ll extend the abstract JsonSerializer class, giving it the type we want to serialize from.

package net.sghill.example;

import net.sghill.example.User;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
import java.io.IOException;

public class UserSerializer extends JsonSerializer {
    @Override
    public void serialize(User user, JsonGenerator jsonGenerator,
            SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("username", user.getUsername());
        jsonGenerator.writeEndObject();
    }
}

Note nothing going to production should be storing a password as plaintext in the database, as would be the case here. This is merely for illustration purposes. BCrypt is the current king of the castle for storing passwords.


Published Apr 15, 2012