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.