Parsing JSON with gson

I recently spent a couple of hours fighting through a jungle of legacy JSON parsing code that resulted in me looking for an easier way to parse data in JSON format. I remembered JSON as the lightweight javascripty data format that came about as a way to circumvent browser restrictions with XML… so why was I knee deep in about 10 jar files that reminded me of working with Xerxes, SAX, DOM, XML Schema, JAXB, and all that other good XML stuff? We’re just trying to parse a string with some colons and curly braces after all. A quick (google) search led me to a (google) project that appeared to be just what the doc ordered. I downloaded the binaries and put together a quick test to see if things worked as advertised. I had two high-level requirements that I wanted to cover in my test:

Be able to serialize/deserialize a hierarchy of objects
Have the ability to easily work with custom data formats

In order to cover the first requirement I created a BorrowRate class that encapsulated some Quotes which effectively created my object hierarchy.

package data;
import java.util.Collection;
import org.joda.time.DateTime;
public class BorrowRate {
 public DateTime validDate;
 public DateTime effectiveDate;
 Collection quotes;

public BorrowRate(DateTime validDate, DateTime effectiveDate,
 Collection quotes) {
 super();
 this.validDate = validDate;
 this.effectiveDate = effectiveDate;
 this.quotes = quotes;
 }

public BorrowRate() {
 super();
 }

public DateTime getValidDate() {
 return validDate;
 }

public void setValidDate(DateTime validDate) {
 this.validDate = validDate;
 }

public DateTime getEffectiveDate() {
 return effectiveDate;
 }

public void setEffectiveDate(DateTime effectiveDate) {
 this.effectiveDate = effectiveDate;
 }

public Collection getQuotes() {
 return quotes;
 }

public void setPoints(Collection quotes) {
 this.quotes = quotes;
 }
}

… and …

package data;
import org.joda.time.DateTime;
public class Quote {
 public DateTime date;
 public Double value;
 public Quote(DateTime date, Double value) {
 super();
 this.date = date;
 this.value = value;
 }

public Quote() {
 super();
 }

public DateTime getDate() {
 return date;
 }

public void setDate(DateTime date) {
 this.date = date;
 }

public Double getValue() {
 return value;
 }

public void setValue(Double value) {
 this.value = value;
 }
}

In order to cover the second requirement I stored my dates as joda date objects. Gson uses reflection to determine how to interpret/translate data that it comes across. This means that you have to give the parser a heads up if you are working with custom datatypes. You do this by registering a custom deserializer.

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeDeserializer());

The above code tells the parser that if it were to come across any joda DateTime fields, it should use the DateTimeSerializer to perform the translation. You might be tempted to use the registerDeserializer method directly (as described in the user guide) but that actually won’t work since the method is private. So make sure to use registerTypeAdapter which you can also use to register custom serializers and InstanceCreator if your classes do not have default empty constructors. Having the default constructor is actually crucial if you do not know how to use InstanceCreator. Without them this example won’t work.

With all the plumbing in place I went ahead and parsed my JSON string:

{"validDate":"2009-04-22T00:00:00","effectiveDate":"2009-04-22T13:44:37","quotes":[{"value":0.25,"date":"2009-05-15T00:00:00"},{"value":0.7,"date":"2009-06-19T00:00:00"},{"value":0.56,"date":"2009-07-17T00:00:00"},{"value":0.4,"date":"2009-09-18T00:00:00"},{"value":0.2,"date":"2009-12-18T00:00:00"},{"value":0.15,"date":"2010-03-19T00:00:00"},{"value":-0.15,"date":"2010-06-18T00:00:00"},{"value":-0.25,"date":"2010-12-17T00:00:00"},{"value":-0.4,"date":"2011-12-16T00:00:00"},{"value":-0.55,"date":"2012-12-20T00:00:00"},{"value":-0.6,"date":"2013-12-20T00:00:00"},{"value":-0.65,"date":"2015-12-18T00:00:00"},{"value":-0.8,"date":"2018-12-21T00:00:00"},{"value":-0.8,"date":"2020-04-19T00:00:00"},{"value":-0.85,"date":"2024-04-18T00:00:00"},{"value":-0.85,"date":"2024-04-19T00:00:00"},{"value":-0.85,"date":"2024-04-20T00:00:00"}]}

All I had to do was to call:

Gson gson = gsonBuilder.create();
BorrowRate borrowRate = gson.fromJson(jsonString, BorrowRate.class);

I printed out the contents of the object and everything seemed to be in order. One small jar file and 4 lines of code … ah yes .. much better.

2 responses to “Parsing JSON with gson

  1. There is an easier way to parse dates now. The gson team has added support for dates so that you can specify the date format.

    Here is their unit test example:

    http://code.google.com/p/google-gson/source/browse/trunk/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java?spec=svn327&r=327

    you should be able to do this and you don’t even have to define a date deserializer class anymore:

    String pattern = “YOUR DATE FORMAT HERE”;
    Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL).setDateFormat(pattern).create();

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s