Core and Advance features of Gson library


Welcome back to last article on the Gson series. After reviewing the basics of Gson, we'll discuss on some core and advance features of it.

All the code is available on GitHub.

Before moving further lets discuss what are the ways to create Gson object?
Gson object can be created in two ways. First way gives you a quick Gson object provides standard configuration and ready for faster coding, while second way uses GsonBuilder to build a more sophisticated Gson object. By using GsonBuilder, you can create a new Gson instance with your customized configuration.


Serialization/De-serialization of Nested Objects

Gson doesn't require any specific configuration to serialize/de-serialize nested objects. It'll automatically infer the structure of the data based on the passed classes. Like-

//Serialize  (where bookObject is instance of Book.java)
String serializedJson = gson.toJson(bookObject);

// De-serialize
Book book = gson.fromJson(INPUT_JSON, Book.class);

In the GsonExample project refer NestedJsonTest.java class for reference code.


Serialization/De-serialization of Arrays/Lists

Arrays
If you want to use Arrays in serialization/de-serialization, it's pretty simple. You can directly use the fromJson() function as we've done before and pass the model class as an array.  Like

//Serialize (where itemArray is array of Item.java)
String serializedJson = gson.toJson(itemArray);

// Deserialize
Item[] items = gson.fromJson(INOUT_JSON, Item[].class);


List
Serialization of List is also straight forward Like

// Serialize
String serializedJson = gson.toJson(myItemList);

In order for Gson to understand the List structure it provides a class TypeToken to assist you in finding the correct Type. For our Item class in an ArrayList, it'd look like this:

Type itemListType = new TypeToken<ArrayList<Item>>(){}.getType(); 
List<Item> itemList = gson.fromJson(INOUT_JSON, itemListType);

In the GsonExample project refer ArrayListJsonTest.java class for reference code.

Important point: Type and TypeToken are the very important classes provided by GSON by which you can create expected data type. For Map, Set or Generics you can also apply the same strategy to parse into appropriate Type.


NULL values

During serialization Gson ignores null values. If a value is not set, it'll not be part of the resulting JSON. This behavior of ignoring null is a good idea to reduce the size of resulting JSON.

If you require that fields with null values in the JSON, Gson has an option for it. We'll utilize the GsonBuilder to adapt the serialization of null values.

Gson gson = new GsonBuilder().serializeNulls().create();
String serializedJson = gson.toJson(employeeDetails);

In the GsonExample project refer NullValueJsonTest.java class for reference code.


Ignore the Fields

It is useful in situations where you want to control if certain field should be considered for Serialization/de-serialization. For that Gson offers a simpler solution with the annotation @Expose. This annotation is applied on field level and is effective only when Gson is created with GsonBuilder and invoking excludeFieldsWithoutExposeAnnotation(). In this manner, only the field which is annotated with @Expose will be considered for serializaion/deserialization.

@Expose offers two configuration parameters: serialize and deserialize. By default both set to true.
Like-

public class UserDetails {


    @Expose

    public String name;



    @Expose(deserialize = false)

    public String gender;



    @Expose(serialize = false, deserialize = false)

    public long phoneNumber;



    @Expose(serialize = false)

    public long cardNumber;


    public int pin;

}

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String serializedJson = gson.toJson(userDetails);

In the GsonExample project refer IgnoreFieldTest.java class for reference code.


Change the Name of Fields

So far, we always assumed the JSON and model class have identical naming. Unfortunately, this is not always the case. If are following Java or Android naming convention, this can create a huge problem for you. In such situations you can use @SerializedName annotation to make Gson's matching still work like a charm.

public class UserData {


    public String name;


    public String gender;


    @SerializedName("phoneNumber")

    public long phoneNo;


    @SerializedName("cardNumber")

    public long cardNo;


    public int pin;

}

In the GsonExample project refer ChangeFieldNameTest.java class for reference code.


Naming Policy

We've already learnt on how to use @SerializedName to change the single field inside a model. However if you are in the initial face of development or   Rest/Soap API and Java models are not agreeing on specific naming it can be tedious to change hundreds of property names with the @SerializedName annotation.

Thus, Gson offers configured and custom FieldNamingPolicys. This can be configured using GsonBuilder. Once you set any of this policy, all conversions using the Gson instance will now apply the field naming policy. In other words GSON conversion will follow the name of fields according to the policy.

Following are the list of FieldNamingPolicys:
·        IDENTITY
·        LOWER_CASE_WITH_DASHES
·        LOWER_CASE_WITH_UNDERSCORES
·        UPPER_CAMEL_CASE
·        UPPER_CAMEL_CASE_WITH_SPACES

You can find more details here.

Here is example of LOWER_CASE_WITH_UNDERSCORES which split the property names based on upper characters and replace those upper characters with a lower one leading with underscore (_).

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy. LOWER_CASE_WITH_UNDERSCORES);
Gson gson = gsonBuilder.create();

{
            "_name": "UserName",
            "gender": "Male",
            "phone_number": 1234567890,
            "card_number": 283808120,
            "pin": 4321
}

In the GsonExample project refer FieldNamingPolicyTest.java class for reference code.


Custom Type Adapters

Gson does the serialization/deserialization using inbuilt adapters. In certain cases you may want to write your own adapters because you want to change the default behaviors or GSON does not provide adapter for your class.

To achieve this you need to create a custom adapter by extending TypeAdapter class and passing it the type of object targeted. Overrides read and write methods to do the custom de-serialization and serialization respectively.

class CustomAdapter extends TypeAdapter<Student> {
            @Override
            public UserDetails read(JsonReader reader) throws IOException {
            ...
            }
            @Override
            public void write(JsonWriter writer, UserDetails userDetails) throws IOException {
            …
            }
}

And then register the custom adapter using GsonBuilder as-

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Student.class, new StudentAdapter());
Gson gson = builder.create();

In the GsonExample project refer FieldNamingPolicyTest.java class for reference code.


Hope this article will help you to control over GSON. 

To find more interesting topics on Software development follow me at https://medium.com/@ankit.sinhal

You can also find my Android Applications on play store


Comments

Popular posts from this blog

Android Performance: Avoid using ENUM on Android

Secure and smaller APK size using Proguard

Smart way to update RecyclerView using DiffUtil