GSON - Gson
Jakob Jenkov |
GSON is Google's JSON parser and generator for Java. Google developed GSON for internal use but open sourced it later. GSON it reasonably easy to use, but in my opinion not as elegant as Jackson or Boon (the winner in my opinion). In this GSON tutorial I will take you through how to use GSON to parse JSON into Java objects, and serialize Java objects into JSON.
GSON contains multiple APIs which you can use to work with JSON. This tutorial covers the Gson
component which parses JSON into Java objects, or generates JSON from Java objects. In addition to the
Gson component GSON also has a pull parser in the GSON JsonReader
component.
Before you can use GSON you must first install GSON in your Java project. I have explained that in its own text about GSON Installation .
Creating a Gson Instance
Before you can use GSON you must first create a new Gson object. There are two ways to create a
Gson instance:
- Using
new Gson() - Creating a
GsonBuilderinstance and callingcreate()on it.
Both of these ways to create a Gson instance will be covered in this GSON tutorial.
new Gson()
You can create a Gson object simply by creating it with the new Gson() instruction.
Here is how creating a Gson object looks:
Gson gson = new Gson();
Once you have created a Gson instance you can start using it to parse and generate JSON.
GsonBuilder.build()
Another way to create a Gson instance is to create a GsonBuilder() and call its
create() method. Here is an example of creating a GsonBuilder and calling create():
GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create();
Using a GsonBuilder allows you to set configuration options on the GsonBuilder before
creating the Gson object. You will see examples of this later in this GSON tutorial.
Parsing JSON Into Java Objects
GSON can pase JSON into Java objects using the fromJson() method of the Gson object.
Here is an GSON example of parsing JSON into a Java object:
String json = "{\"brand\":\"Jeep\", \"doors\": 3}";
Gson gson = new Gson();
Car car = gson.fromJson(json, Car.class);
The first line of the example defines the JSON string to parse. The second line creates a Gson instance.
The third line calls the gson.fromJson() method which parses the JSON string into a Car
object.
The first parameter to fromJson() is the JSON source. In the example above the JSON source is a string.
The second parameter to the fromJson() method is the Java class to parse parse the JSON into an instance
of. The Gson instance creates an instance of this class and parses the JSON into it. Thus you should
make sure that this class has a no-arg constructor, or GSON cannot use it.
Here is how the Car class looks:
public class Car {
public String brand = null;
public int doors = 0;
}
Generating JSON From Java Objects
GSON can also generate JSON from Java objects. You do so via the Gson object. To generate JSON you
call the toJson() method of the Gson object. Here is an example of generating JSON from
a Java object with GSON:
Car car = new Car(); car.brand = "Rover"; car.doors = 5; Gson gson = new Gson(); String json = gson.toJson(car);
Pretty Printing
By default the Gson instance created with new Gson() prints (generates) as compact as
possible JSON. Here is an example of the compact JSON output from a default Gson instance:
{"brand":"Rover","doors":5}
However, this compact JSON can be hard to read. Therefore GSON offers a pretty printing option
where the JSON is printed so it is more readable in a text editor. Here is an example of how to create a
Gson instance with pretty print enabled:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Here is an example of how the same JSON would look pretty printed:
{
"brand": "Rover",
"doors": 5
}
Excluding Fields
You can tell GSON to exclude fields from your Java classes from being serialized. There are several ways to tell GSON to exclude a field. The following sections of GSON tutorial will look at the most useful and easy to use ways to exclude fields.
Transient Fields
If you make a field in a Java class transient then GSON will ignore it in both serialization and
deserialization. Here is how the Car class from earlier looks with the brand field
marked as transient:
public class Car {
public transient String brand = null;
public int doors = 0;
}
The @Expose Annotation
The GSON @Expose annotation (com.google.gson.annotations.Expose) can be used to mark a
field to be exposed or not (included or not) when an object is serialized or deserialized.
The @Expose annotation can take two parameters. Each
parameter is a boolean which can take either the value true or false.
Here are some GSON @Expose annotation examples to show what I mean:
@Expose(serialize = true); @Expose(serialize = false); @Expose(deserialize = true); @Expose(deserialize = false); @Expose(serialize = true , deserialize = false); @Expose(serialize = false, deserialize = true);
The @Expose annotation's serialize parameter specifies if the field annotated with the
@Expose annotation should be included when the owning object is serialized. The deserialize
parameter specifies whether that field should be read when the owning object is deserialized.
Here is an example class using the GSON @Expose annotation:
public class Car {
@Expose(serialize = false, deserialize = false)
public String brand = null;
@Expose(serialize = true, deserialize = true)
public int doors = 0;
}
Notice the @Expose annotation above the fields, telling whether the given field should
be included when serialized or deserialized.
In order to get GSON to react to the @Expose annotations you must create a Gson
instance using the GsonBuilder class. Here is how that looks:
GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); Gson gson = builder.create();
Note, that this configuration makes GSON ignore all fields that do not have an @Expose
annotation. To have a field included in serialization or deserialization it must have an @Expose
annotation above it.
GsonBuilder.setExclusionStrategies()
Another way to exclude a field of a class from serialization or deserialization in GSON is to set an
ExclusionStrategy on a GsonBuilder, and use that GsonBuilder to build
the Gson object with.
ExclusionStrategy is an interface, so you will have to create a class that implements the
ExclusionStrategy interface. Here is an example that implements the ExclusionStrategy
interface with an anonymous class:
ExclusionStrategy exclusionStrategy = new ExclusionStrategy() {
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
if("brand".equals(fieldAttributes.getName())){
return true;
}
return false;
}
public boolean shouldSkipClass(Class aClass) {
return false;
}
};
Notice that inside the shouldSkipField() method of the ExclusionStrategy implementation
the example checks if the given field name is brand. If it is, that field is excluded from
serialization and deserialization.
To use the ExclusionStrategy implementation create a GsonBuilder and set the
ExclusionStrategy on it using the setExclusionStrategies() method, like this:
GsonBuilder builder = new GsonBuilder(); builder.setExclusionStrategies(exclusionStrategy); Gson gson = builder.create();
The exclusionStrategy variable has to point to an implementation of the ExclusionStrategy
interface.
Serializing Null Fields
By default the Gson object does not serialize fields with null values to JSON. If
a field in a Java object is null, Gson excludes it.
You can force Gson to serialize null values via the GsonBuilder.
Here is an example showing how to force serialization of null values with GSON:
GsonBuilder builder = new GsonBuilder(); builder.serializeNulls(); Gson gson = builder.create(); Car car = new Car(); car.brand = null; String json = gson.toJson(car); System.out.println(json);
Notice the call to serializeNulls() on the GsonBuilder instance before creating
the Gson object. Once serializeNulls() has been called the Gson instance
created by the GsonBuilder will include null fields in the serialized JSON.
The output from the above example would be:
{"brand":null,"doors":0}
Notice how the brand field is null.
Custom Instance Creators in GSON
By default GSON will try to create an instance of a given class by calling the no-arg constructor of that class. However, if a given class does not have a default constructor, or you want to do some default configuration of the instance, or if you want to create an instance of a subclass instead, you need to create and register your own instance creator.
A GSON instance creator is simply an object factory. An instance creator has to implement the
InstanceCreator interface (com.google.gson.InstanceCreator). Here is an example
InstanceCreator implementation:
import com.google.gson.InstanceCreator;
public class CarCreator implements InstanceCreator<Car> {
public Car createInstance(Type type) {
Car car = new Car();
car.brand = "Toyota";
return car;
}
}
You use the above CarCreator class by registering it on a GsonBuilder before you create
the Gson instance. Here is an example:
GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Car.class, new CarCreator()); Gson gson = gsonBuilder.create();
Now the Gson instance will use the CarCreator instance to create Car
instances. You can prove that to yourself by running this code (after the CarCreator has been registered):
String carJson = "{ \"doors\" : 4 }";
Car car = gson.fromJson(carJson, Car.class);
System.out.println(car.brand);
The default brand property value is null and the JSON string does not contain a
brand property. Therefore you will see the value for the brand property set inside
the CarCreator's createInstance() method (Toyota).
Version Support in GSON
GSON contains simple version support for the Java objects it reads and writes. GSON version support means that you can mark fields in your Java classes with a version number, and then have GSON include or exclude fields from your Java classes based on their version number.
To use GSON version support you must first annotate your Java classes with the GSON @Since annotation.
Here is an example Person class with its fields annotated with the @Since annotation:
import com.google.gson.annotations.Since;
public class Person {
@Since(1.0)
public String firstName = null;
@Since(1.0)
public String lastName = null;
@Since(2.0)
public String middleName = null;
@Since(3.0)
public String email = null;
}
Second, you must create a GsonBuilder and tell it what version it should be serializing to and
deserializing from. Here is an example of how you create a GsonBuilder and set the version number on it:
GsonBuilder builder = new GsonBuilder(); builder.setVersion(2.0); Gson gson = builder.create();
The Gson instance created from the above GsonBuilder will now just include fields that
are annotated with @Since(2.0) or a lower version number than 2.0 . In the Person example
class above that means the fields firstName, lastName and middleName.
The email field is annotated with version 3.0 which is later than 2.0, so GSON will exclude the email
field.
Here is an example of serializing a Person object to JSON and look at the generated JSON:
Person person = new Person(); person.firstName = "John"; person.lastName = "Doe"; person.middleName = "Blocks"; person.email = "john@doe.com"; GsonBuilder builder = new GsonBuilder(); builder.setVersion(2.0); Gson gson = builder.create(); String personJson = gson.toJson(person); System.out.println(personJson);
This example will print out the following JSON string:
{"firstName":"John","lastName":"Doe","middleName":"Blocks"}
Notice how GSON excluded the email field in the generated JSON.
Excluding fields based on version works the same for reading JSON into Java objects (deserialization).
Look at the following JSON string which contains all the fields, including the email field:
"{\"firstName\":\"John\",\"lastName\":\"Doe\",\"middleName\":\"Blocks\",\"email\":\"john@doe.com\"}"
If you were to read a Person object with the above Gson object, the email
field will not be read even if it is present in the JSON string. Here is how reading a Person
object with the above Gson instance would look:
String personJson2 = "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"middleName\":\"Blocks\",\"email\":\"john@doe.com\"}";
Person personRead = gson.fromJson(personJson2, Person.class);
Custom Serialization and Deserialization
GSON offers the possibility for you to plug in customer serializers and deserializers. Your custom serializers can convert Java values to custom JSON, and your custom deserializers can convert custom JSON to Java values again.
Custom Serializer
A custom serializer in GSON has to implement the JsonSerializer interface. The JsonSerializer
interface looks like this:
public interface JsonSerializer<T> {
public JsonElement serialize(T value, Type type,
JsonSerializationContext jsonSerializationContext) {
}
}
Implementing a custom serializer that can serializer boolean values looks like this:
public class BooleanSerializer implements JsonSerializer<Boolean> {
public JsonElement serialize(Boolean aBoolean, Type type,
JsonSerializationContext jsonSerializationContext) {
if(aBoolean){
return new JsonPrimitive(1);
}
return new JsonPrimitive(0);
}
}
Notice how the T type parameter is replaced with the Boolean class in two places.
Inside the serialize() method you can convert the value (a Boolean in this cas) to
a JsonElement which the serialize() method is required to return. In the example
above we use a JsonPrimitive which is also a JsonElement. As you can see, boolean
values of true are converted to 1 and false to 0, instead of true
and false normally used in JSON.
Registering this custom serializer is done like this:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Boolean.class, new BooleanSerializer()) ; Gson gson = builder.create();
It is the call to registerTypeAdapter() which registers the customer serializer with GSON.
Once registered, the Gson instance created from the GsonBuilder will use the
custom serializer. To see how that works we will use the following POJO class:
public class PojoWithBoolean {
public String username = null;
public Boolean isSuperUser = false;
}
Here is how serializing a PojoWithBoolean instance looks:
PojoWithBoolean pojo = new PojoWithBoolean(); pojo.username = "abc"; pojo.isSuperUser = false; String pojoJson = gson.toJson(pojo); System.out.println(pojoJson);
The output printed from this example would be:
{"username":"abc","isSuperUser":0}
Notice how the false value of isSuperUser is converted to a 0.
Custom Deserializer
GSON also provides support for custom deserializers. A custom deserializer must implement the
JsonDeserializer interface. The JsonDeserializer interface looks like this:
public interface JsonDeserializer<T> {
public Boolean deserialize(JsonElement jsonElement,
Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException;
}
Implementing a custom deserializer for the Boolean type would look like this:
public class BooleanDeserializer implements JsonDeserializer<Boolean> {
public Boolean deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
return jsonElement.getAsInt() == 0 ? false : true;
}
}
Registering the custom deserializer with GSON is done using another version of the registerTypeConverter()
method. Here is how registering the above deserializer with GSON looks:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Boolean.class, new BooleanDeserializer()); Gson gson = builder.create();
And here is how parsing a JSON string with the created Gson instance looks:
String jsonSource = "{\"username\":\"abc\",\"isSuperUser\":1}";
PojoWithBoolean pojo = gson.fromJson(jsonSource, PojoWithBoolean.class);
System.out.println(pojo.isSuperUser);
The output printed from this GSON custom deserializer example would be:
true
... since the 1 in the JSON string would be converted to the boolean value true .
| Tweet | |
Jakob Jenkov | |











