🌱 Digital Garden

Search

Search IconIcon to open search

Last updated Aug 5, 2023 Edit Source

# Customizing JSON with Gson

You an use the GsonBuilder class to modify the default behavior of Gson objects. If you need ultimate control over the fine details of serializaiton/deserialization, you can create your own classes that implement the JsonSerializer and or JsonDeserializer interfaces.

# 1. GsonBuilder

Gson library provides a convenient object for configuring the basic behavior of Gsons JsonObjets.

GsonBuilder class is implemented using the builder design pattern, so you can chain a bunch of its methods together on an object instance to set the desired behavior.

1
2
3
4
5
6
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder
    .setPrettyPrinting()
    .serializeNulls()
    .excludeFieldsWithoutExposeAnnotation()
    .create();

We can create an String representing the gson.toJson method to see what we end up with inside the file.

# 2. Custom serialization

We can customize the way it converts our object into JSON. We create a custom serializer class that implements the JsonSerializer interface and overrides its serialize() method. We configure it for our class by passing our class in as a type argument.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class GuitarBrandGsonSerializer implements JsonSerializer<GuitarBrand> {
     
    @Override
    public JsonElement serialize(GuitarBrand guitar, Type type,
        JsonSerializationContext jsonSerializationContext) {
        
        JsonObject guitarJsonObj = new JsonObject();
        
        // Code to customize the JsonObject

        return guitarJsonObj;
    }
}

We need to fill in the details for how we want to customize the JsonObject. First, we can customize the name of the JSON properties so that they don’t just follow the Java class property names. We can use addProperty() method to do that, first parameter is for the chosen name as a String, the second is for the value of the oebject we are assigning to that name.

1
2
guitarJsonObj.addProperty("brand_name", guitar.getName());
guitarJsonObj.addProperty("country_founded_in", guitar.getCountry());

If we want to add an array as a value, we can do it using add() method.

1
2
3
4
5
JsonArray array = new JsonArray();
if (guitar.getArtistsUsedBy() != null) {
    guitar.getArtistsUsedBy().forEach(array::add);
}
guitarJsonObj.add("<strong>Artists Who Use</strong>", array);

# 3. Custom deserialization

There may be times when you want the data to be deserialized in a certain way. The following example demonstrates that inside the deserialize method you have the liberty to do any modifications you want to the JsonObject date before creating and returning the Java object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class GuitarBrandGsonDeserializer implements JsonDeserializer<GuitarBrand> {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public GuitarBrand deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {

        JsonObject jsonObject = json.getAsJsonObject();

        JsonElement jsonGuitarBrandName = jsonObject.get("name");
        JsonElement jsonDateFounded = jsonObject.get("dateOfBirth");
        JsonElement jsonCountry = jsonObject.get("country");
        JsonArray jsonArtistsUsedBy = jsonObject.getAsJsonArray("artistsUsedBy");

        ArrayList<String> artistList = new ArrayList<>();
        if (jsonArtistsUsedBy != null) {
            for (int i = 0; i < jsonArtistsUsedBy.size(); i++) {
                artistList.add(jsonArtistsUsedBy.get(i).getAsString());
            }
        }

        GuitarBrand guitarBrand = new GuitarBrand(sdf.parse(jsonDateFounded.getAsString()), 
                                  jsonGuitarBrandName.getAsString(), 
                                  jsonCountry.getAsString(), artistList);
        return guitarBrand;
}

If you define your custom serializer carefully, the default deserializer will often be enough. Custom deserialization is especially important when you don’t have access to the class files for serialized objects, or when the JSON objects contain more information than you need.

# 4. Tying it all together

In order for a Gson object to use our customized class, we need to register it using a GsonBuilder object. We do this using the registerTypeAdapter() method, to which we pass the class we are serializing/deserializing and an instance of our custom class.

1
2
3
4
Gson gson = new GsonBuilder()
    .registerTypeAdapter(GuitarBrand.class, new GuitarBrandGsonSerializer())
    .disableHtmlEscaping()
    .create();

The exact same process is used for registering a deserializer. Once this is done, the Gson object can be used in the same way as when we used the default Gson object.

# 5. Conclusion

We looked at ways of customizing the behavior of Gson to suit your needs. The GsonBuilder class can be used to make minor changes to the default behavior of Gson objects, such as setting bettter-looking printing, serializing nulls, escaping HTML and only serializing fields with @Expose annotations.

When absolute control over serialization and deserialization is required, we can create custom classes, define their behavior, and register them with GsonBuilder’s registerTypeAdapter() method.