Google GSON for JSON Processing

Google GSON for JSON Processing

JavaScript Object Notation (JSON) is a lightweight data exchange format. Like XML, JSON provides a way of representing object that is both human readable and machine processable.

JSON is the most commonly used data exchange format on the Web. In the Java ecosystem, several libraries which that you can use to serialize Java objects to JSON, transmit the JSON data over a network, and deserialize the JSON back to Java objects.

In this post, we’ll take a look at using the GSON library, which stands for Google JSON.

The Maven POM

In order to use GSON, you need the JAR files of the GSON library in your project classpath. If you are using Maven, include the GSON dependency in your Maven POM.

The first parameter of the fromJson() method is the source JSON that must be converted into Product. In our example it is the json variable of type String. The second parameter is the Product object (POJO) that will be initialized with the JSON.

Note: Ensure that the POJO to which the JSON is converted to has a no-argument constructor. This is required so that Gson can create an instance of this class.

Excluding Fields from being Serialized or Deserialized

At times you might not want certain fields of a POJO to be serialized or deserialized. GSON allows you to exclude such fields from your POJO.

One of the several ways of excluding fields is by using the transient keyword.

If you declare any field in the Java class as transient, Gson ignores it during both serialization and deserialization.

The code to declare a field as transient is this.

private transient String version;

When you serialize the object to JSON, you will find that the version field of the POJO is not serialized.

To summarize, a field marked as transient ensures that it will neither be serialized nor deserialized.

However, at times you need more control. You might need that a field should be serialized but never deserialized, and vice-versa.

For such requirements, use the @Expose annotation of Gson. This annotation tells whether or not to include a field during either serialization, deserialization, or both. For example, using the @Expose annotation, you can tell that the version field should only be serialized, and not deserialized back. Similarly the other way around.

The @Expose annotation takes one, both, or none of the two elements: serialize and deserialize, both of which are of Boolean type.

The Product POJO fields after applying the @Expose annotation is this.

In this code, the imageUrl field is marked with the @Expose annotation with the serialize element set to false and deserialize set to true. Therefor the imageUrl field will only be deserialized from JSON, but will not be serialized.

The price field is marked with @Expose, and therefore by default, it’s both serialize and deserialize elements are set to true. Therefore the The price field will both be serialized and deserialized.

You need to explicitly tell Gson to use the @Expose annotation like this.

Custom Serialization and Deserialization

So far, we have converted JSON into Java object and vice versa using the default Gson implementation.

However, at times, you may want to configure the serialization and deserialization processes. For example, you might need to specifically map a particular POJO field with a JSON key having a different name.

To do so, you can use the JsonSerializer and JsonDeserializer interfaces.

By default, Gson uses the field names as keys in the JSON. For example, the class has a field named productId, while the same field is represented as product-id in the required JSON.

To serialize the Java object into the expected JSON, you need to create a custom serializer class that implements the JsonSerializer interface. The code shows a custom serializer class.

The Type parameter of the JsonSerializer interface is the type of the object to be serialized. Here an instance of Product is serialized.

The return type of the overridden serialize() method is a JsonElement. The JsonElement can be of four concrete types. One among them is JsonObject, a key-value pair where the value itself is a type of JsonElement.

To serialize the Product object, you need an instance of JsonElement. This example uses JsonObject. This object is populated with the fields as required in the JSON using the addProperty() method. Finally, the serialize() method returns the populated JsonObject.

To use this serializer, you need to register it through the GsonBuilder.

By default, Gson parses the JSON when it finds the fields in the object class with same name as it holds. So Gson by default would expect the fields of the Product class to be product-id, description, image-url, and price.

However, it is common to have different fields in the POJO class. In our example, the JSON has a key product-id while the productId field represents the same in the Product class. Same is with the image-url key whose corresponding field in Product is imageUrl.

As a result, the default serializer of Gson will not be able to deserialize the product-id and image-url keys to their corresponding fields in Product.

In order to parse this JSON into an object of Product class you can use a custom deserializer that implements the JsonDeserializer interface.

The code of the custom deserializer is this.

The JsonDeserializer interface takes a Type parameter which is the type of Java class to which the JSON will be converted to. Here it is the Product class.

The CustomProductSerializer class overrides the deserialize() method of JsonDeserializer which returns an instance of Product.

In the deserialize() method, the call to the getAsJsonObject() method converts the JsonElement passed as argument to deserialize() into JsonObject. The values within the JsonObject are themselves JsonElement which can be retrieved by their names. To convert these elements into their respective reference types, the getXXX() methods are called.

To use this deserializer, you need to register it through the GsonBuilder. The code to register and use the custom deserializer is this:

Using GSON with Spring Boot

Out of the box, Spring Boot uses Jackson as the JSON parser library. If you wish to learn more about Jackson, check out this blog post.

But you can seamlessly pull in Gson in your Java application for JSON processing. To include Gson, you need to configure the GsonHttpMessageConverter. Whenever a request hits the controller, the @RestController annotation asks Spring to directly render the object as model to the response.

Spring looks for HttpMessageConverter to convert the Java object into JSON.

Spring by default configures the MappingJackson2HttpMessageConverter for this conversion. But to use Gson you need to configure Spring Boot to use GsonHttpMessageConverter instead.

To avoid conflicts with the use of Jackson and Gson, use the annotation @EnableAutoConfiguration(exclude = { JacksonAutoConfiguration.class }) in your application class and exclude the Jackson dependency from your POM.

Validate the GSON Converter

To verify that our Spring Boot application is indeed using the Gson converter, let’s create a controller class with a request handler method that handles the request to the default request mapping to the root /.

As you can see, the Spring Framework is using GSON’s GsonHttpMessageConverter to convert Product to JSON instead of the default Jackson library.

Summary

As you can see in this post, Spring Boot is very flexible in allowing JSON parsers, like GSON to be plugged in for parsing JSON.

Gson is a complete JSON parser with extensive support of Java Generics. Gson supports custom representations for objects and arbitrarily complex objects having deep inheritance hierarchies.

In terms of usage, I found Gson to be fairly simple. The API is intuitive and with minimal changes to source code, you can address complex serialization and deserialization requirements of JSON to and from Java objects.