Gson Builder — Basics & Naming Policies

Datetime:2016-08-23 03:09:49          Topic:          Share

In the previous blog posts in this series you've learned how to use Gson to convert Java objects to JSON and vice versa. So far, we've shown you how to set up models and what's important in order to get the correct mapping going. With this blog post we'll start a new multi-post part of this series which will use the GsonBuilder to customize several pieces of Gson's behavior.

Of course, this isn't the only post in our Gson series. If you're interested in the other topics, check out our series outline:

Gson Series Overview

  1. Getting Started with Java-JSON Serialization & Deserialization
  2. Mapping of Nested Objects
  3. Mapping of Arrays and Lists of Objects
  4. Mapping of Maps
  5. Mapping of Sets
  6. Mapping of Null Values
  7. Gson Model Annotations — How to Ignore Fields with @Expose
  8. Gson Model Annotations — How to Change the Naming of Fields with @SerializedName
  9. Gson Builder — Basics & Naming Policies
  10. Gson Builder — Force Serialization of null Values
  11. Gson Builder — Exclusion Strategies
  12. Gson Builder — Relax Gson with Lenient
  13. Gson Builder — Special Values of Floats & Doubles
  14. Gson Builder — Model Versioning
  15. Gson Builder — Formatting of Dates & Custom Date/Time Mapping
  16. Gson Builder — Pretty Printing
  17. Gson Builder — HTML Escaping
  18. Gson Advanced — Generics

GsonBuilder Basics

In all the previously published blog posts we've written that you can just get an instance of Gson with Gson gson = new Gson(); . This is totally valid when you need Gson with its standard configurations. However, Gson has a lot of little settings you can change. This is quite convenient if you need to utilize Gson in a way which is slightly non-standard. In order to change certain settings you can use the GsonBuilder to create a new Gson instance with your customized configuration.

// previously
Gson gson = new Gson();

// now using GsonBuilder
GsonBuilder gsonBuilder = new GsonBuilder();  
Gson gson = gsonBuilder.create();

The GsonBuilder class offers a .create() method which returns a Gson instance. With the Gson instance you can do everything we've shown you before: map all kinds of data from and to JSON.

Naming Policies

The first GsonBuilder option we want to show you are naming policies. We've always assumed that your Java model files and the JSON payload for request and responses of the API apply the same naming schema. We've shown you how to use @SerializedName to change the serialization of a single model property. However, if your API and your Java models are not agreeing on naming it can be tedious to change hundreds of property names with the @SerializedName annotation.

Thus, Gson offers configured and custom FieldNamingPolicy s. For demonstration purposes we adjusted our UserSimple model and gave the properties some new names:

public class UserNaming {  
    String Name;
    String email_of_developer;
    boolean isDeveloper;
    int _ageOfDeveloper;
}

As you can see, we're unifying all kind of naming standards in one model. This will result in some funny looking JSONs, but makes it easier to see how the various naming policies will affect them. You can set the policy on the GsonBuilder:

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

All conversions using the above Gson instance will now apply the field naming policy FieldNamingPolicy.IDENTITY . In the next few sections we'll explore what exactly that means and how the predefined field naming policies behave. Let's start with the easiest one: IDENTITY .

FieldNamingPolicy - IDENTITY

The field naming policy IDENTITY uses the exact same naming as the Java model when it serializes an object. No matter with what naming standard you set up your Java models, the JSON will use the same ones. Our strangely named model above would result in the following JSON:

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

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

The usersJson would contain:

{
  "Name": "Norman",
  "_ageOfDeveloper": 26,
  "email_of_developer": "norman@futurestud.io",
  "isDeveloper": true
}

As you can see, none of the field names changed. It copied the exact names from the model. If you're not setting a policy or don't use the GsonBuilder and directly instantiate a Gson with new Gson() it'll use this policy.

FieldNamingPolicy - LOWER_CASE_WITH_UNDERSCORES

The second policy we would like to show you is LOWER_CASE_WITH_UNDERSCORES . The naming is pretty clear, but let's use it on our sample model:

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

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

The LOWER_CASE_WITH_UNDERSCORES will split up the property names based on upper characters and replace those upper characters with a lower one leading with a _ . For our model two properties are affected:

{
  "name": "Norman",
  "_age_of_developer": 26,
  "email_of_developer": "norman@futurestud.io",
  "is_developer": true
}

The isDeveloper and _ageOfDeveloper got split up with _ . Note that the leading _ of _ageOfDeveloper is still there! If you don't want to use underscores and instead prefer dashes, the next section might be something for you.

FieldNamingPolicy - LOWER_CASE_WITH_DASHES

The third option we would like to show you is LOWER_CASE_WITH_DASHES . It uses the same system as the previous LOWER_CASE_WITH_UNDERSCORES , but replaces the field name separation with - . Let's apply the following code:

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

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

This will result in a usersJson with the following content:

{
  "name": "Norman",
  "_age-of-developer": 26,
  "email_of_developer": "norman@futurestud.io",
  "is-developer": true
}

Please note how it still only changed the two properties with upper case letters in them. The leading underscore of _ageOfDeveloper or the underscores of email_of_developer are not affected! If you need a more strict policy, you can implement your own logic, which we'll show you in a minute. But before moving to custom policies, it's time for the last two predefined ones.

FieldNamingPolicy - UPPER_CAMEL_CASE

The fourth policy is UPPER_CAMEL_CASE , which makes the first letter upper case. You hopefully know by now how to apply a naming policy using the GsonBuilder :

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

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

The resulting usersJson would be:

{
  "Name": "Norman",
  "_AgeOfDeveloper": 26,
  "Email_of_developer": "norman@futurestud.io",
  "IsDeveloper": true
}

You can see that this is the first policy that affects all four properties. It changes all of them to start with an upper case letter, even if the property name starts with a leading _ . This policy doesn't change the separation though. It leaves underscores the same. The next one changes the word separation a bit:

FieldNamingPolicy - UPPER_CAMEL_CASE_WITH_SPACES

The last policy UPPER_CAMEL_CASE_WITH_SPACES is almost identical to UPPER_CAMEL_CASE . The code is almost the same anyway:

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

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

Let's look at the resulting usersJson :

{
  "Name": "Norman",
  "_Age Of Developer": 26,
  "Email_of_developer": "norman@futurestud.io",
  "Is Developer": true
}

As you can see, not much changed from UPPER_CAMEL_CASE . The only difference is that the two fields, which already had upper case letters, received spaces in between the words.

Interaction with @SerializedName

You might be wondering how the policies interact with @SerializedName . We've demonstrated the usage of @SerializedName in anearlier blog post. Let's change our UserNaming model to utilize @SerializedName :

public class UserNaming {  
    String Name;

    @SerializedName("emailOfDeveloper")
    String email_of_developer;

    boolean isDeveloper;
    int _ageOfDeveloper;
}

What happens when you apply a naming policy now? The answer is that it'll leave the property with the @SerializedName untouched. For example, if we use UPPER_CAMEL_CASE , it'll result in this JSON:

{
  "Name": "Norman",
  "_AgeOfDeveloper": 26,
  "emailOfDeveloper": "norman@futurestud.io",
  "IsDeveloper": true
}

The emailOfDeveloper stayed exactly as in the @SerializedName annotation and did not get a leading upper case letter.

Custom Field Naming

The provided policies in combination with the @SerializedName might not be enough to cover your use case. You can implement your own version of the FieldNamingPolicy . Since you can only pass pre-defined enum values to the .setFieldNamingPolicy() method, Gson offers a second method .setFieldNamingStrategy() .

You can pass an instance of the FieldNamingStrategy to the appropriate method. The FieldNamingStrategy class only has a single method. For example, if we would want to remove all underscores , which none of the predefined policies do, we could use the following code snippet:

FieldNamingStrategy customPolicy = new FieldNamingStrategy() {  
    @Override
    public String translateName(Field f) {
        return f.getName().replace("_", "");
    }
};

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingStrategy(customPolicy);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);  
String usersJson = gson.toJson(user);

The resulting JSON would not contain any underscores anymore:

{
  "Name": "Norman",
  "ageOfDeveloper": 26,
  "emailOfDeveloper": "norman@futurestud.io",
  "isDeveloper": true
}

Gson only accepts one strategy. Thus, you've to implement your logic in a single FieldNamingStrategy implementation. If you call one of the methods we've shown you above more than once, it'll replace the previous one.

Deserialization

In this blog post we've only looked at the serialization side of things. In other words how does the JSON look like after we've used Gson to convert the data from Java objects. All of these naming policies have the same effect during deserialization. Basically, if you've an API which returns all values in lower case with underscores as separation between words you could use the LOWER_CASE_WITH_UNDERSCORES as policy and use regular Java naming conventions in your model.

As a simple example, if you've the following JSON:

{
  "reviewer_name": "Marcus"
}

You can have the following model:

public class PostReviewer {  
    String reviewerName;
}

If you apply the correct naming strategy, Gson will do the mapping even though the names are different.

Outlook

In this blog post, you've learned the basics of using the GsonBuilder . We looked at a first option to customize Gson's behavior. In particular, we've shown you a variety of policies to customize property naming during the (de)serialization of Java objects.

In the next blog post, we'll continue to show you more GsonBuilder capabilities. Specifically, we'll introduce a way to force Gson to serialize null values.

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io .

Make it rock & enjoy coding!

Not enough Gson? Buy our book!

Enjoy JSON (de-)serialization in Java. Learn every detail about Gson's capabilities, configuration & customization.

Including a workbook & a cheat sheet!

Available on Leanpub