A Convenient way to convert JSON to business entity : GSON – Part1

06 / Nov / 2015 by Anand Rai 0 comments

Before swimming in Gson, I think we should take a bath with JSON. So What is JSON? These days JSON is set as standard for transmitting data between servers and web applications, known as Java Script object notation is a lightweight data interchange format.

Now Gson is a java library provided by Google to convert to/from Java to JSON representation. Gson is an open-source project hosted at http://code.google.com/p/google-gson.

Why we use GSON

  1. Converts any Java Object to JSON and vice-versa.
  2. Excellent support for generics object.
  3. No need of any annotation for field for conversion.
  4. It handles null field for serialization and for deserialization null field would not be handled.
  5. If you don’t want include any field dusing serializaion, use transient modifier for that field.

Go with the performance and scalability test

  1. Deserialized strings of over 25MB without any problems
  2. Serialized a collection of 1.4 million objects.

How we are going to use it

1) For this need to use primary class GSON by calling new Gson(). There is also one more class GsonBuilder available to create Gson instance for varoius version

[code]Gson gson = new Gson();[/code]

2) For conversion of an object to/from json, need to use the Gson class and its following two methods.

toJson()- converts an object to json string, takes object as argument and returns the json string.

[code]gson.toJson(10); ==> prints 10
gson.toJson("xyz"); ==> prints "abcd"
gson.toJson(new Long(10)); ==> prints 10
int[] values = { 1 };
gson.toJson(values); ==> prints [1] [/code]

fromJson()-converts the json string to object, takes first param as json string as object and class literal of destination object and returns the destination object.

[code]int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String anotherStr = gson.fromJson("[\"abc\"]", String.class); [/code]

Adding gson in project

Using Maven

Add the following dependency to project’s pom.xml

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

Using Gradle

Add following to project’s build.gradle

[code]
repositories {
mavenCentral()
}

dependencies {

compile ‘com.google.code.gson:gson:2.2.4’
}
[/code]

The Gson instance does not maintain any state while invoking Json operations. So, you are free to reuse the same object for multiple Json serialization and deserialization operations.

Object Examples

[code]

class SumOfNumber {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
SumOfNumber() {
// no-args constructor
}
}
[/code]

(Serialization)

[code]SumOfNumber obj = new SumOfNumber();
Gson gson = new Gson();
String json = gson.toJson(obj);
==> json is {"value1":1,"value2":"abc"}
[/code]

Note that you can not serialize objects with circular references since that will result in infinite recursion.

(Deserialization)

[code]SumOfNumber obj2 = gson.fromJson(json, SumOfNumber.class); [/code]

==> obj2 is just like obj

Hanlde Null field during serialization

[code]
Gson gson = new Gson();
Map<String,Object> map = new HashMap<String, Object>();
map.put("a", 1);
map.put("b", null);
System.out.println(gson.toJson(map)); //prints {"a":1}
[/code]

If you want to add all entry or we can say you want to change default behaviour you need to use

[code]Gson gson = new GsonBuilder().serializeNulls().create();[/code]

Annotations in GSON

In gson annotation 5 interfaces has defined which are :

  1. SerializedName
  2. Expose
  3. Until
  4. Since
  5. JsonAdapter

Going forward towards explaning these interfaces we can start with SerializedName

SerializedName

public @interface SerializedName

This define that member will be serailized to JSON with the provided value as its in the field name.
Here is the example to use this.

[code]
public class Car {
@SerializedName("carBrand")
private final String carBrandField;
private final String carModelField;

public Car(String a, String b) {
this.carBrandField = a;
this.carModelField = b;
}
}
[/code]

Here is the output that is generated when serializing an instance of the above example:

[code]
Car carObject = new Car("Maruti", "Suzuki");
Gson gson = new Gson();
String convertedJson = gson.toJson(carObject);
System.out.println(convertedJson);
[/code]

=====Output=====

[code]
{"carBrand":"Maruti","carModelField":"Suzuki"}
[/code]

As per my point of view you should not use this annotation to avoid your extra efferot, use filedName same as serailizedName.

Expose

public @interface Expose

This denotes that member will be exposed during serialization and deserialization. But this annotation has no effect unless we build Gson with GsonBuilder and invoke following method.

[code]Gson gsonObj=new GsonBuilder.excludeFieldsWithoutExposeAnnotation().create(); [/code]

Here is an example of how this annotation is meant to be used:

[code]
public class Car {
@Expose private String carBrand;
@Expose(serialize = false) private String carModel;
@Expose (serialize = false, deserialize = false) private String fuelType;
private String mileage;
}
[/code]

If we use Gson with new Gson(), the toJson() and fromJson() will use mileage along with carBrand,carModel and fuelType during serailization and deserialization. However if you created gson instance using new GsonBilder().excludeFieldsWithoutExposeAnnotation().create() then the toJson() and fromJson() methods of Gson will exclude the mileage field. This is because the mileage field is not marked with the @Expose annotation. Gson will also exclude carModel and fuelType from serialization since serialize is set to false. Similarly, Gson will exclude fuelType from deserialization since deserialize is set to false.

You can also achieve this effect using mileage field set as transient, and Gson would have excluded it even with default settings.

[code]private transient String mileage;[/code]

Until

public @interface Until

This annotaion denotes the version number until a member or a type should be present.That means if Gson is created with a version number that exceeds the value stored in the Until annotation then the field will be ignored from the JSON output.

This annotation also has no effect unless yu use GsonBuilder() for creating gson instance.

Here is an example of how this annotation is meant to be used:

[code]
public class Car {
private String carBrand;
private String carModel;
@Until(1.1) private String fuelType;
@Until(1.1) private String mileage;
}

[/code]

If you created Gson with

[code]Gson gson = new GsonBuilder().setVersion(1.2).create()[/code]

then the toJson() and fromJson() methods of Gson will exclude the fuelType and mileage fields from the example above, because the version number passed to the GsonBuilder, 1.2, exceeds the version number set on the Until annotation, 1.1, for those fields.

Since

public @interface Since

This annotation indication that since a member or type has been present. This is very usefule for maintaining version of your JSON classes.

This annotation also has no effect unless you use GsonBuilder() and invoke GsonBuilder.setVersion(double) method for creating new instance.

Here is an example of how this annotation is meant to be used:

[code]
public class Car {
private String carBrand;
private String carModel;
@Since(1.0) private String fuelType;
@Since(1.1) private String mileage;
}
[/code]

If you created Gson with

[code]Gson gson = new GsonBuilder().setVersion(1.0).create()[/code]

then the toJson() and fromJson() methods of Gson will exclude the mileage field since it’s version number is set to 1.1.

JsonAdapter

That’s all for part 1. Sorry for JsonAdapter but this annotation is a blog in itself with TypeAdapter. So wait for my next blog for JSONAdapter.

Key Points

  1. This is absolutley fine (and recommended) to use private fields
  2. There is no need to use any annotations to indicate a field is to be included for serialization and deserialization. All fields in the current class (and from all super classes) are included by default.
  3. If a field is marked transient, (by default) it is ignored and not included in the JSON serialization or deserialization.
  4. This implementation handles nulls correctly
  5. While serialization, a null field is skipped from the output
  6. While deserialization, a missing entry in JSON results in setting the corresponding field in the object to null
  7. Fields corresponding to the outer classes in inner classes, anonymous classes, and local classes are ignored and not included in serialization or deserialization
FOUND THIS USEFUL? SHARE IT

Tag -

GSON

Leave a Reply

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