In this tutorial we look at how to selectively include fields from a java object to a json string. By default, Gson tries to map all fields in the java object to the corresponding property in json. However, in certain cases we may want to control that. There are a few ways to do this. It is also possible to excluse fields from third party packages where we have no access to the source code. The different ways to exclude fields are :
- By defining a custom annotation and ignoring fields that are annotated with that.
- By Defining a custom exclusion class by extending the ExclusionStrategy interface and implementing the public boolean shouldSkipField(FieldAttributes f); and public boolean shouldSkipClass(Class clazz); methods
- By using the @Expose annotations and then using the excludeFieldsWithoutExposeAnnotation() method on the GsonBuilder. This will ignore all fields except the ones that have been exposed using the @Expose annotation.
Just as we saw in the previous tutorial, Gson provides way to specify custom serializers and deserializers. Register a custom serializer with the GsonBuilder if you need you own way to convert a java object to json and you a custom deserializer if you dont like Gson’s way of converting json to the java object. The first example below shows a custom serializer and the second example shows a custom deserializer.
Custom Serializer
Create a custom serializer by implementing a com.studytrails.json.gson.JsonSerializer and implementing the public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context); method. src is the source object and Type is the type of the source object. The example below demonstrates a custom Serializer.
In the earlier tutorials we have seen how gson can serialize and deserialize java classes with or without hierarchies. By default, it introspects the classes and comes with with a strategy for serializing and deserializing it. However, in some cases, you want to specify your own conversion strategy. That is, you want to control how the java object is converted to json string and the other way round. Gson provides a capability to specify a custom type adapter. You tell Gson that for a particular class, use the conversion strategy specified by your custom adapter. Lets look at how to write the type adapter :
To write a custom adapter extend the com.google.gson.TypeAdapter abstract class. Implement the public abstract T read(JsonReader in) throws IOException; and public abstract void write(JsonWriter out, T value) throws IOException; methods. The adapter should also handle nulls. Create the Type adapter instance and then register it with the GsonBuilder. Create the Gson object from the GsonBuilder and then use that to serialize and deserialize. Lets look at an example
package com.studytrails.json.gson;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class DatasetTypeAdapterExample8 {
public static void main(String[] args) throws MalformedURLException, IOException {
String url = "http://freemusicarchive.org/api/get/albums.json?api_key=60BLHNQCAOUFPIBZ&limit=5";
String json = IOUtils.toString(new URL(url));
// Create the custom type adapter and register it with the GsonBuilder
// class.
Gson gson = new GsonBuilder().registerTypeAdapter(Dataset.class, new DatasetTypeAdapter()).create();
// deserialize the json to Albums class. The Dataset objects are part of
// the Albums class. Whenever Gson encounters an object of type DataSet
// it calls the DatasetTypeAdapter to read and write json.
Albums albums = gson.fromJson(json, Albums.class);
System.out.println(albums.getDataset()[1].getAlbum_title());
// prints
// http://freemusicarchive.org/music/The_Yes_Sirs/Through_The_Cracks_Mix_Vol_1/
}
}
Serializing inner classes
Gson can serialize inner classes and static nested classes. The detailed example below demonstrates the following things.
- Serializing class containing static nested class
- Serializing class containing non static nested class (Inner class)
- De-serializing json to a class containing static and non static inner class
- Serializing static nested class (without the enclosing type)
- Serializing non static nested class (without the enclosing type)
- De-serializing json to a static nested class (without the enclosing type)
- De-serializing json to a non static nested class (without the enclosing type)
Serializing list
As we saw in the previous tutorial serializing and deserializing classes with generic types is non trivial since generic type information is lost while serializing. Gson provides a class called com.google.gson.reflect.TypeToken to store generic types. The example below shows how to use the TypeToken class to serialize and deserialize Classes with generic types.
package com.studytrails.json.gson;
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class GenericTypesExample8 {
public static void main(String[] args) {
// create an animal class that is of type dog.
Animal animal = new Animal<Dog>();
// Create a Dog instance
Dog dog = new Dog("I am a dog");
animal.setAnimal(dog);
Gson gson = new Gson();
// Define a Type that is an Animal of type dog.
Type animalType = new TypeToken<Animal<Dog>>() {
}.getType();
// we first convert the animal object to a json and then read the json
// back. However we define the json to be of Animal type
Animal animal1 = gson.fromJson(gson.toJson(animal, animalType), Animal.class);
System.out.println(animal1.get().getClass()); // prints class
// com.google.gson.internal.LinkedTreeMap
// In contrast to above where we read the json back using the Animal
// type, here we read the json back as the custom animalType Type. This
// gives Gson an idea of what
// the generic type should be.
Animal animal2 = gson.fromJson(gson.toJson(animal), animalType);
System.out.println(animal2.get().getClass());
// prints class com.studytrails.json.gson.Dog
}
}
Serializing list
Serializing Collections should have been similar to serializing other objects. However, the problem is that Collections are generic and the generic type information is not maintained in the json. We therefore pass the type while deserializing list. Note that if the Collection has different types of objects then there is no way to serialize it.
package com.studytrails.json.gson;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class DeSerializeListExample5 {
public static void main(String[] args) {
String json = "[{album_id:1,album_title:'album1'},{album_id:2,album_title:'album2'}]";
Gson gson = new Gson();
// create the type for the collection. In this case define that the collection is of type Dataset
Type datasetListType = new TypeToken<Collection<Dataset>>() {}.getType();
List<Dataset> datasets = gson.fromJson(json, datasetListType);
for (Dataset dataset : datasets) {
System.out.println(dataset.getAlbum_title());
System.out.println(dataset.getAlbum_id());
}
// Prints
//album1
//1
//album2
//2
}
}
In the Earlier tutorial we saw how to convert json to a java object. In this tutorial, we build a tree of com.google.gson.JsonElement from the json string. The tree can then be traversed to build java objects. JsonElement has methods such as isJsonObject(), isJsonNull(), etc that can be used to figure out the type of JsonElement. Then to get the actual object use the getAsJsonObject(), getAsJsonPrimitive() etc methods. We parse the response from the free music archive json API. Here’s the class
In the earlier tutorials we saw how to convert json to a java object. In This tutorial we see how to parse json and obtain individual tokens. Although this may seem like a cumbersome way to build java object from json, however it is extremely powerful and may be a good choice if you need a very high level of control over the parsing. We use the JsonReader class to read the json as a stream of tokens. The beginning of an object or an array is also a token. Here’s a detailed example.
Google json provides methods to convert the json string to java objects. The Java object may be hierarchical. For this example we consider java objects of non generic type only. Gson uses the name to match the json property to the java field. There are two ways to convert json to java.
- Using the com.google.gson.Gson class. Create a new instance of this class and use the method public T fromJson(String json, Class classOfT). classOfT is the java object to which the json is to be converted to.
- The other way is to use the com.google.gson.GsonBuilder class. This class allows setting up certain features, such as - allowing null serialization or setting up custom serializing policies. Create a GsonBuilder, apply the features and then obtain the Gson class from the builder.
In this tutorial we look at the Gson class to de-serialize json from free music archive. The main class is the Albums class and it contains the list of Datasets. Each Dataset is one album. The way to approach the problem of deserialization is to build a java class such that the when Gson converts the Java class to JSON, the resultant JSON resembles the one we are trying to parse. Lets see this in action. If you look at the JSON, it starts with a root object that has properties such as title, message, errors, etc.
{
title: "Free Music Archive - Albums",
message: "",
errors: [ ],
total: "11259",
total_pages: 2252,
page: 1,
limit: "5",
dataset: [
{
......
google json - gson is an open source java api for parsing and building json. It has extensive support for java generics. It also provides support for converting third party classes to json. It can be used to serialize and deserialize complex objects with deep hierarchies that may contain generic classes. In these tutorials we demonstrate, with examples, the following functionalities of gson.
Gson 2.3: Look at this tutorial to see the
latest additions in Gson 2.3 (TypeAdapter Annotation, JsonPath support and new methods in JsonArray)
-
Java to JSON and Back - Data Binding - In this example we look at how to bind a Json to a java object. Gson is quite powerful when it comes to binding a json to Java since it has a lot of built in serializers and deserializers. A serializer has code that helps in converting a Json string to corresponding java type. For example if you have an array in JSON (elements enclosed in ‘[’ and ‘]’) and you want to convert that to a Java array then Gson would internally use an ArrayTypeAdapter to convert the Json Array to Java Array and back. If you are looking at Gson primarily to parse JSON then we would suggest that you start with a simple Java class, convert that to JSON and make sure it looks like the JSON that you want to parse. You can then gradually start adding complexities to the java class and at each step convert it to a JSON and ensure that the JSON is similar to the one that you are trying to parse. It is good to think of parsing a JSON as creating a java class that can give you the JSON that you want to parse. Also note that you have certain flexibility while creating the java object. You could represent a Json Array as a Java array or a Java List. The choice may be driven more by how you want to use the class. If you map a Json property to a java array Gson would use an Array adapter but if you map it to a List it would use the collection adapter and you, the user, does not have to worry about that. Gson also handles null gracefully
-
Java to JSON and Back - Streaming - At certain times you want more control on the way the parsing is done. Also there may be times when Gson automated conversion does not give you the result that you are looking for. For example, if you have a List that contains multiple kinds of Object then Gson may not be able to deserialize or parse the Json for you. In such cases Gson provides a streaming API. You can use the Streaming API and handle a token at a time. The token may be start and end of Json Object, start and end of json array, the key of a property and the String or Number value of a property.