Gson vs Jackson: Which to Use for JSON in Java

There are many JSON libraries for Java. While it’s nice to have many options, it can also be frustrating to decide which one to use. If you do an online search, you will find many opinions and all these libraries are used somewhere. When in doubt, the best thing to do is: stop searching and start coding. It doesn’t take long to get the ultimate answer for you.

That is what I did for one project – I wrote two samples based on the top two parser for de-serializing a JSON string, serializing a Java object, and of course comparing performance with a reasonably large JSON file. At the end, I summarize what I had found. If you don’t want to read the code and detailed discussion, just jump to the conclusion at the end.

Bothered by SLOW Web UI to manage vSphere? Want to manage ALL your VMware vCenters, AWS, Azure, Openstack, container behind a SINGLE pane of glass? Want to search, analyze, report, visualize VMs, hosts, networks, datastores, events as easily as Google the Web? Find out more about vSearch 3.0: the search engine for all your private and public clouds.

For fair comparison, I first wrote something in GSON and then copy it to use Jackson APIs. That is why you will find most of the lines are exactly the same.

Sample Code 1: Using Jackson

To run the code, you will need a JSON file called bigjson.json. You can copy and paste from your own data, or simply use an online generator to create one. If you don’t want to evaluate performance, just comment out the section of code.

package org.doublecloud.json.sample;
 
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
/**
 *
 * @author steve jin (http://www.doublecloud.org)
 */
public class JacksonDemo
{
  private static ObjectMapper mapper = new ObjectMapper();
 
  public static void main(String[] args) throws IOException
  {
    parseJson();
 
    saveJson();
 
    perfTest();
  }
 
  public static void parseJson() throws IOException
  {
    String jsonStr = "{ \"author\": \"Steve Jin\", \"title\" : \"vSphere SDK\", \"obj\" : {\"objint\" : {}} }";
 
    // parsing JSON to generic object
    Object obj = mapper.readValue(jsonStr, Object.class);
    System.out.println("obj type: " + obj.getClass().toString()); // java.util.LinkedHashMap
    System.out.println("obj: " + obj);
 
    // parsing JSON to Map object
    Map m = mapper.readValue(jsonStr, Map.class);
    System.out.println("map.size: " + m.size());
    for(Object key: m.keySet())
    {
      System.out.println("key:" + key);
    }
 
    // parsing JSON to concrete Object
    Book book = mapper.readValue(jsonStr, Book.class);
    System.out.println("book: " + book);
    System.out.println("book.author: " + book.author);
    System.out.println("book.obj class: " + book.obj.getClass()); //com.google.gson.internal.LinkedTreeMap
    System.out.println("book.obj: " + book.obj);
  }
 
  public static void saveJson() throws IOException
  {
    Book book = new Book();
    book.author = "Steve Jin";
    book.title = "VMware vSphere and VI SDK";
 
    mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY);
    String bookJson = mapper.writeValueAsString(book);
    System.out.println("bookJson: " + bookJson);
  }
 
  public static void perfTest() throws IOException
  {
    long start = System.nanoTime();
 
    mapper.readValue(new File("src/main/resources/bigjson.json"), Map[].class);
 
    long end = System.nanoTime();
    System.out.println("Time taken (nano seconds): " + (end - start));
  }
}
 
class Book
{
  public String author;
  public String title;
  public Map obj;
}

To run the code, you will need the following dependency if using Maven:

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.3</version>
            <type>jar</type>
        </dependency>

Sample Code 2: Using GSON

This code shares the same Book class from the above sample. To run it without the first sample, you want to copy the few lines to the following.

 
package org.doublecloud.json.sample;
 
import com.google.gson.Gson;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
 
/**
 *
 * @author steve jin (http://www.doublecloud.org)
 */
public class GsonDemo
{
  private static Gson gson = new Gson();
 
  public static void main(String[] args) throws IOException
  {
    parseJson();
 
    saveJson();
 
    perfTest();
  }
 
  public static void parseJson() throws IOException
  {
    String jsonStr = "{ \"author\": \"Steve Jin\", \"title\" : \"vSphere SDK\", \"obj\" : {\"objint\" : {}} }";
    Object obj = gson.fromJson(jsonStr, Object.class);
 
    System.out.println("obj type: " + obj.getClass().toString()); // com.google.gson.internal.LinkedTreeMap
    System.out.println("obj: " + obj);
 
    Map m = gson.fromJson(jsonStr, Map.class);
    System.out.println("m: " + m.size());  // 3
 
    for(Object key: m.keySet())
    {
      System.out.println("key:" + key);
    }
 
    Book book = gson.fromJson(jsonStr, Book.class);
    System.out.println("book: " + book);
    System.out.println("book.author: " + book.author);
    System.out.println("book.obj class: " + book.obj.getClass()); //com.google.gson.internal.LinkedTreeMap
    System.out.println("book.obj: " + book.obj);
  }
 
  public static void saveJson() throws IOException
  {
    Book book = new Book();
    book.author = "Steve Jin";
    book.title = "VMware vSphere and VI SDK";
 
    String bookJson = gson.toJson(book);
    System.out.println("bookJson: " + bookJson);
  }
 
  public static void perfTest() throws IOException
  {
    long start = System.nanoTime();
 
    // http://www.json-generator.com/# for generating a JSON file
    gson.fromJson(new FileReader("src/main/resources/bigjson.json"), Map[].class);
 
    long end = System.nanoTime();
    System.out.println("Time taken (nano seconds): " + (end - start));
  }
 
}

If you use Maven, you will need the following dependency:

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.2.4</version>
        </dependency>

Comparison: Features and Performance

From the API perspective, the GSON and Jackson are very similar even though they use different terminologies for the same thing. The Gson type in gson is very much like the ObjectMapper in Jackson. One difference I found on the serializing Java object to JSON string is that by default Jackson write out the properties whose value is null. Gson is just the opposite. There is a switch to change the Jackson default as shown in the code.

There is nothing wrong with the default. It’s just a matter of context and sometimes personal preference. For example, if you want to serialize an object to be deserialized later in free form, you want to include properties even with null values; otherwise the information is lost later on. If you will deserialize it as a concrete object later, there isn’t much difference except for some saving on Json string size.

Although there isn’t much difference on the APIs, I find myself in slight preference of Gson with its elegant toJson() and fromJson(). I think that is probably because I used similar fromXml() and toXml() in the vijava Web Service engine.

Now let’s take a look at the performance. I used a Json string with an array of objects generated from this site. The file size is about 5K bytes. It took 2,121,000 nano-seconds using Gson; and 12,784,000 nano-seconds using Jackson. There is 6 times difference where Gson is a clear winner. Again, the difference is probably not visible in most cases except in those heavy duty server applications.

Update: as a follow up article, here is how to pretty print JSON with Gson and Jackson.

This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

6 Comments

  1. Posted March 27, 2015 at 1:48 pm | Permalink

    Quick note on performance: the way performance is measured here mostly measures time it takes for JVM to warm up to the use case. If serialization was run 10 times in a row, the last time will be significantly faster than the first. So unless the specific goal is to measure performance for starting JVM, doing one operation, then shutting down, results are not representative.

    For this reason Java performance benchmark always include some level of warming up: either by number of repetitions, or number of seconds to run before taking measurements.
    Additionally tests include number of operations and calculate either average time (total time divided by number of repetitions), or use minimum time.

    So: unless the expected use case is a single read and/or write for the lifetime of a JVM, I think results mentioned will not be representative of actual performance.
    Both GSON and Jackson will be an order of magnitude faster after warmup, and you will get better view of relative performance for sustained use.

  2. Posted March 27, 2015 at 3:25 pm | Permalink

    Thanks a lot for the info. Agree that performance comparison may not be representative due to the JVM warm up. The result may also depend on the sample data – one parser may perform faster on data with certain patterns.

    BTW, I notice Jackson uses the java.util.LinkedHashMap in Java standard library and Gson uses its own Map implementation: com.google.gson.internal.LinkedTreeMap. Does it make any difference in performance? Thanks!

    Steve

  3. Posted March 27, 2015 at 5:25 pm | Permalink

    In the test case you are not using List/Map representation but binding to/from POJOs, so Maps are not necessarily used. I think GSON may use different Map for security reasons (there was a possible hash-collision problem in JDK 1.6, earlier 1.7), and not for performance reasons.

    But if you are interested in seeing if there is a performance difference there (my guess is that GSON’s version is bit slower due to using additional hashing), you can read JSON as Map and measure.

  4. Posted April 4, 2015 at 4:23 pm | Permalink

    Good web site you have got here.. It’s hard to find quality writing like
    yours nowadays. I truly appreciate people like you!
    Take care!!

  5. Posted April 11, 2015 at 3:58 pm | Permalink

    If you want accurate timing measurements, check out jmh from Oracle. The issues that you have to solve to get realistic estimates of code performance in Java are non-trivial and much more than just warmup is involved.

    See http://www.oracle.com/technetwork/articles/java/architect-benchmarking-2266277.html

  6. Posted July 28, 2016 at 11:50 pm | Permalink

    Gson vs Jackson: Which to Use for JSON in Java
    https://t.co/JbJfeS4mmy

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  • NEED HELP?


    My company has created products like vSearch ("Super vCenter"), vijavaNG APIs, EAM APIs, ICE tool. We also help clients with virtualization and cloud computing on customized development, training. Should you, or someone you know, need these products and services, please feel free to contact me: steve __AT__ doublecloud.org.

    Me: Steve Jin, VMware vExpert who authored the VMware VI and vSphere SDK by Prentice Hall, and created the de factor open source vSphere Java API while working at VMware engineering. Companies like Cisco, EMC, NetApp, HP, Dell, VMware, are among the users of the API and other tools I developed for their products, internal IT orchestration, and test automation.