Jackson Basics, Custom Serializer for mongoDB Objectid with Jackson
Jackson and googl’s Gson library are the most leading JSON serializers available for java, in simple words these libraries can convert a given java object directly to its JSON equivalent.
In this blog post I’m covering
- basics usage of Jackson
- few Jackson annotations
- creating custom serializer when needed
for this tutorial you will be needing jackson-core , jackson-annotations, jackson-databind so before start please download the required jar files, if you are maven fan here are the maven signatures
com.fasterxml.jackson.core
jackson-core
2.4.1.1
com.fasterxml.jackson.core
jackson-annotations
2.4.1
com.fasterxml.jackson.core
jackson-databind
2.4.1.2
POJO to JSON
when dealing with Jackson it is most recommend to create single instance from ObjectMapper and reuse it again and again, unless this will be huge performance hit
import java.io.StringWriter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class Client {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class ClientDemo{
private final static ObjectMapper map = new ObjectMapper();
public static void main(String[] args) throws Exception{
Client cl = new Client();
cl.setName("Mr Jhon");
cl.setAge(30);
//jackson in action :)
map.configure(SerializationFeature.INDENT_OUTPUT, true);
StringWriter json = new StringWriter();
map.writeValue(json, cl);
System.out.println("---------------------JSON----------------------");
System.out.println(json);
}
}
JSON to POJO
class ClientDemo{
private final static ObjectMapper map = new ObjectMapper();
public static void main(String[] args) throws Exception{
String json = "{ \"name\" : \"Mr Jhon\", \"age\" : 30 }";
ObjectMapper map = new ObjectMapper();
Client cl = (Client)map.readValue(json, Client.class);
System.out.println("---------------------Client attributes----------------------");
System.out.println("Name "+cl.getName());
System.out.println("age "+cl.getAge());
}
}
Few Jackson annotations
Jackson annotations can be used to handle the way of Json/Object mapping
@JsonProperty(“yourname”) : This can be used to rename a property
@JsonIgnore : This is used to avoid particular attribute appearing in json
@JsonSerialize(as=CustomSerializer.class) : Define a custom serializer for a particular property
@JsonDeserialize(as=CustomDeSerializer.class) : Define a custom deserialize for a particular property
There are few other annotations but these are the once that will commonly used when working with Jackson, here is an example Class annotated
public class Client {
private String name;
private int age;
@JsonProperty("yourname")
public String getName() {
return name;
}
@JsonProperty("yourname")
public void setName(String name) {
this.name = name;
}
@JsonIgnore
public int getAge() {
return age;
}
@JsonIgnore
public void setAge(int age) {
this.age = age;
}
}
Here is the resulting JSON
{
"yourname" : "Mr Jhon"
}
Writing Custom Serializer
In rare occasions we might want to change the behavior of the Jackson serializer in order to perform a different way of serialization. you might find this is very occasional when working with mongodb and its java driver, lets assume that your database for storing Client object is mongodb then since mongodb is having a hexadecimal id as the primary key you will have to modify your class like this
public class Client {
private ObjectId id;
private String name;
private int age;
public ObjectId getId() {
if(id == null){
return id = new ObjectId();
}
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
now lets say that you have populated this class with data retrieved from mongodb (you might use spring-mongo wrapper), and you need to create a JSON from the new instance, but if you use jackson directly, this is the JSON you will receive
{
"id" : {
"date" : 1405865773000,
"time" : 1405865773000,
"timestamp" : 1405865773,
"inc" : -397946567,
"machine" : 1850976359,
"new" : true,
"timeSecond" : 1405865773
},
"name" : "Mr Jhon",
"age" : 30
}
now this is very ugly, if you are creating a REST service you can’t send this to the client because client make no scene of any attributes of “id” client only need the 32 length hexadecimal id which mongodb has right now, to achieve this it is possible to write a custom serializer
here is the full code of writing custom serialize and using it for our Client object
public class Client {
private ObjectId id;
private String name;
private int age;
@JsonSerialize(using=ObjectID_Serializer.class)
public ObjectId getId() {
if(id == null){
return id = new ObjectId();
}
return id;
}
@JsonSerialize(using=ObjectID_Serializer.class)
public void setId(ObjectId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class ObjectID_Serializer extends JsonSerializer{
@Override
public void serialize(ObjectId objid, JsonGenerator jsongen, SerializerProvider provider) throws IOException, JsonProcessingException {
if(objid == null ){
jsongen.writeNull();
}else{
jsongen.writeString(objid.toString());
}
}
}
after implementing the above code here is what you get as the json
{
"id" : "53cbd0a46e530853e215ee8f",
"name" : "Mr Jhon",
"age" : 30
}