Jackson vs Gson in Java

In this post, we will compare the Gson and Jackson APIs for serializing and deserializing JSON data to Java objects and vice-versa.

Gson Maven dependency   — latest version can be found here

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>

Serialization with Gson

public class Employe {

    private String firstName;
    private String lastName;
    private int age;      
    private BigDecimal salary;
    private List<String> skills;

    //getters and setters
}

Gson Serialization

//Skills 
List<String> skills = new LinkedList<String>();
skills.add("Database");
skills.add("J2EE Programming");
skills.add("RestFul");

//Employe
Employe emp = new Employe();
emp.setFirstName("David");
emp.setLastName("Peter");
emp.setAge(33);
emp.setSalary(new BigDecimal("110000"));
emp.setSkills(skills);

//Serialization - conversion to json string
Gson gson = new Gson();
String serializedEmployee = gson.toJson(emp); 
System.out.println(serializedEmployee);

Sample output:

{  
   "firstName":"David",
   "lastName":"Peter",
   "age":33,
   "salary":110000,
   "skills":[  
      "Database",
      "RestFul",
      "J2EE Programming"
   ]
}

Gson Deserialization

//from the above code deserialize 
Employee emp2 = gson.fromJson(serializedEmployee, Employe.class)

If you compare both emp and emp2 they both are identical

Jackson Maven Dependency

You can get the latest version of Jackson here

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

Jackson Serialization

public class User {
    public int id;
    public String name;
}
public class Item {
    public int id;
    public String itemName;
    public User owner;
}

Now, let’s serialize an Item entity with a User entity:

Item myItem = new Item(1, "iPhone", new User(2, "AppleUser"));
String serialized = new ObjectMapper().writeValueAsString(myItem);

The output looks like this:

{
    "id": 1,
    "itemName": "iPhone",
    "owner": {
        "id": 2,
        "name": "AppleUser"
    }
}

Custom Serializer on the ObjectMapper

import java.time.LocalDateTime;

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public JacksonConfig() {
        objectMapper = new ObjectMapper();
        SimpleModule s = new SimpleModule();
        s.addSerializer(Timestamp.class, new TimestampSerializerTypeHandler());
        s.addDeserializer(Timestamp.class, new TimestampDeserializerTypeHandler());
        objectMapper.registerModule(s);
    };

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return objectMapper;
    }
}

where the serializer should be something like this:

import java.io.IOException;
import java.sql.Timestamp;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class TimestampSerializerTypeHandler extends JsonSerializer<Timestamp> {

    @Override
    public void serialize(Timestamp value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        String stringValue = value.toString();
        if(stringValue != null && !stringValue.isEmpty() && !stringValue.equals("null")) {
            jgen.writeString(stringValue);
        } else {
            jgen.writeNull();
        }
    }

    @Override
    public Class<Timestamp> handledType() {
        return Timestamp.class;
    }
}

and deserializer something like this:

import java.io.IOException;
import java.sql.Timestamp;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class TimestampDeserializerTypeHandler extends JsonDeserializer<Timestamp> {

    @Override
    public Timestamp deserialize(JsonParser jp, DeserializationContext ds) throws IOException, JsonProcessingException {
        SqlTimestampConverter s = new SqlTimestampConverter();
        String value = jp.getValueAsString();
        if(value != null && !value.isEmpty() && !value.equals("null"))
            return (Timestamp) s.convert(Timestamp.class, value);
        return null;
    }

    @Override
    public Class<Timestamp> handledType() {
        return Timestamp.class;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *