Recent from talks
Contribute something
Nothing was collected or created yet.
This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these messages)
|
| Google Gson | |
|---|---|
| Developer | |
| Initial release | May 22, 2008 |
| Stable release | |
| Repository | |
| Written in | Java |
| Operating system | Cross-platform |
| License | Apache License 2.0 |
| Website | github |
Gson, or Google Gson, is an open-source Java library that serializes Java objects to JSON (and deserializes them back to Java).
History
[edit]The Gson library was originally developed for internal purposes at Google, with Version 1.0 released on May 22, 2008, under the terms of the Apache License 2.0.
Usage
[edit]Gson utilizes reflection, meaning that classes do not have to be modified to be serialized or deserialized. By default, a class only needs a defined default (no-args) constructor; however, this requirement can be circumvented (see Features).
The following example demonstrates the basic usage of Gson when serializing a sample object:
package example;
public class Car {
public String manufacturer;
public String model;
public double capacity;
public boolean accident;
public Car() {
}
public Car(String manufacturer, String model, double capacity, boolean accident) {
this.manufacturer = manufacturer;
this.model = model;
this.capacity = capacity;
this.accident = accident;
}
@Override
public String toString() {
return ("Manufacturer: " + manufacturer + ", " + "Model: " + model + ", " + "Capacity: " + capacity + ", " + "Accident: " + accident);
}
}
package example;
public class Person {
public String name;
public String surname;
public Car[] cars;
public int phone;
public transient int age;
public Person() {
}
public Person(String name, String surname, int phone, int age, Car[] cars) {
this.name = name;
this.surname = surname;
this.cars = cars;
this.phone = phone;
this.age = age;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Name: ").append(name).append(" ").append(surname).append("\n");
sb.append("Phone: ").append(phone).append("\n");
sb.append("Age: ").append(age).append("\n");
int i = 0;
for (Car car : cars) {
i++;
sb.append("Car ").append(i).append(": ").append(car).append("\n");
}
return sb.toString();
}
}
package main;
import example.Car;
import example.Person;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class Main {
public static void main(String[] args) {
// Enable pretty printing for demonstration purposes
// Can also directly create instance with `new Gson()`; this will produce compact JSON
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Car audi = new Car("Audi", "A4", 1.8, false);
Car skoda = new Car("Škoda", "Octavia", 2.0, true);
Car[] cars = {audi, skoda};
Person johnDoe = new Person("John", "Doe", 2025550191, 35, cars);
System.out.println(gson.toJson(johnDoe));
}
}
Calling the code of the above Main class will result in the following JSON output:

{
"name": "John",
"surname": "Doe",
"cars": [
{
"manufacturer": "Audi",
"model": "A4",
"capacity": 1.8,
"accident": false
},
{
"manufacturer": "Škoda",
"model": "Octavia",
"capacity": 2.0,
"accident": true
}
],
"phone": 2025550191
}
Since the Person's field age is marked as transient, it is not included in the output.
package main;
import example.Person;
import com.google.gson.Gson;
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
String json = "{\"name\":\"John\",\"surname\":\"Doe\",\"cars\":[{\"manufacturer\":\"Audi\",\"model\":\"A4\"," +
"\"capacity\":1.8,\"accident\":false},{\"manufacturer\":\"Škoda\",\"model\":\"Octavia\",\"capacity\"" +
":2.0,\"accident\":true}],\"phone\":2025550191}";
Person johnDoe = gson.fromJson(json, Person.class);
System.out.println(johnDoe.toString());
}
}
To deserialize the output produced by the last example, you can execute the code above, which generates the following output:
Name: John Doe
Phone: 2025550191
Age: 0
Car 1: Manufacturer: Audi, Model: A4, Capacity: 1.8, Accident: false
Car 2: Manufacturer: Škoda, Model: Octavia, Capacity: 2.0, Accident: true
This shows how Gson can be used with the Java Platform Module System for the example above:
module GsonExample {
requires com.google.gson;
// Open package declared in the example above to allow Gson to use reflection on classes
// inside the package (and also access non-public fields)
opens example to com.google.gson;
}
For more extensive examples, see Gson's usage guide on their GitHub repository.
Features
[edit]- Gson can handle collections, generic types, and nested classes (including inner classes, which cannot be done by default).
- When deserializing, Gson navigates the type tree of the object being deserialized, which means that it ignores extra fields present in the JSON input.
- The user can:
- write a custom serializer and/or deserializer so that they can control the whole process, and even deserialize instances of classes for which the source code is inaccessible.
- write an InstanceCreator, which allows them to deserialize instances of classes without a defined no-args constructor.
- Gson is highly customizable, as you can specify:
- Compact/pretty printing (whether you want compact or readable output)
- How to handle null object fields — by default they are not present in the output
- Excluding fields — rules of what fields are intended to be excluded from deserialization
- How to convert Java field names
References
[edit]- Jenkov, Jakob. "GSON - Gson". tutorials.jenkov.com. Retrieved 2023-12-28.
- Gson, Google, 2023-12-28, retrieved 2023-12-28
External links
[edit]- Gson on GitHub
- Gson tutorial with examples Archived 2020-10-31 at the Wayback Machine
Further reading
[edit]new Gson() or customization through GsonBuilder, enabling methods like toJson() for serialization and fromJson() for deserialization.[4] Key features include handling of complex object graphs, support for Java generics, custom type adapters for specialized serialization, and generation of compact, human-readable JSON output.[4] It performs efficiently with large datasets, such as deserializing strings exceeding 25 MB or serializing collections of over 1.4 million objects, and integrates seamlessly with build tools like Maven and Gradle, particularly in Android development.[4][5]
Widely adopted in the Java ecosystem, Gson is utilized by over 27,000 Maven artifacts and remains a popular choice for JSON processing due to its minimal configuration requirements and robustness.[5] As of 2023, it is in maintenance mode, with bug fixes but no major new features planned. As of the latest release, version 2.13.2 on September 10, 2025, it continues to receive updates for compatibility with modern Java versions, having dropped support for Java 7 and earlier in version 2.12.[1][6][5]
Introduction
Overview
Gson is an open-source Java library developed by Google that facilitates the bidirectional conversion of Java objects to and from JSON strings, enabling seamless serialization and deserialization in applications requiring data interchange in JSON format.[1] It provides a straightforward API for handling complex object graphs, including support for generics, custom types, and annotations to customize the conversion process.[1] The library's core functionality revolves around two primary methods:toJson() for serializing Java objects into JSON strings and fromJson() for deserializing JSON strings back into Java objects.[1] Gson employs a reflection-based approach to inspect and manipulate object structures during these conversions.[1] Initially released on May 22, 2008, with version 1.0, it has evolved to support Java versions starting from Java 8 in its latest release, version 2.13.2, dated September 10, 2025.[2][1]
The source code and releases for Gson are hosted on GitHub under the repository google/gson, where it is maintained as an active project with contributions from the community.[1]
Licensing and Availability
Gson is released under the Apache License, Version 2.0, a permissive open-source license that grants users the right to use, copy, modify, merge, publish, distribute, sublicense, and sell copies of the software, including for commercial purposes, subject to the conditions of providing notice of the original copyright and license terms.[1][7] This license also requires that any modifications or derivative works retain the same licensing terms and include appropriate attribution to the original authors at Google. The library is publicly available through the Maven Central Repository, where it is distributed as the artifact com.google.code.gson:gson, enabling easy integration into Java projects via dependency management tools such as Maven and Gradle.[5] Developers can download pre-built JAR files directly from the official GitHub releases page or access the source code repository for compilation and customization.[6] Community involvement in Gson's development occurs primarily through the GitHub repository, where users submit bug reports, feature requests, and code improvements via issues and pull requests, fostering ongoing enhancements under the project's open-source model.[1]Development
History
Gson was initially developed internally at Google in mid- to late 2007 to address challenges in JSON serialization and deserialization for Java applications, particularly the need for robust type validation and schema enforcement during processing.[8] The library was designed to leverage Java reflection for mapping fields across inheritance hierarchies, enabling efficient handling of arbitrary and pre-existing objects without relying on external frameworks like Guice for instance creation.[8] This approach allowed Google engineers to convert Java objects to JSON and back while minimizing dependencies, making it suitable for internal projects requiring lightweight JSON integration.[8][4] Recognizing its broader utility, Google transitioned Gson to an open-source project under the Apache License 2.0, with the initial Version 1.0 released on May 22, 2008.[2] The release provided a standalone Java library focused on simplicity and performance, quickly attracting interest from developers seeking a dependency-free solution for JSON tasks in Java environments.[2] Following its open-sourcing, Gson saw early adoption within ongoing Google products, where it continued to support internal JSON needs across multiple projects.[4] Externally, it gained traction among developers and public projects for its straightforward API, contributing to its integration into ecosystems like the Android SDK in subsequent years.[4]Releases and Maintenance
Gson has undergone iterative releases since its early development, with major versions introducing enhancements in Java compatibility, type handling, and security. Version 2.8.0, released on October 27, 2016, added built-in support for Java 8'sjava.time API, enabling direct serialization and deserialization of classes like LocalDate and ZonedDateTime without custom adapters. This release also improved generic type resolution via new static methods in TypeToken, such as getParameterized and getArray, and introduced null safety features for custom TypeAdapter implementations through the @JsonAdapter(nullSafe=true) annotation.[9]
Later milestones focused on modern Java features and robustness. Gson 2.10, released on October 25, 2022, incorporated support for Java records (available in Java 16 and later), facilitating their serialization and deserialization as standard objects. It also added convenience methods like JsonArray.asList() and JsonObject.asMap() for easier manipulation of JSON structures, alongside fixes for reflective type adapters and stricter null handling in arrays. Version 2.12.0, released on January 27, 2024, dropped support for Java 7—establishing Java 8 as the minimum requirement—and introduced NullSafeTypeAdapter to prevent null pointer exceptions in serialization pipelines.[6]
More recent updates have emphasized bug fixes, security, and module system integration. Gson 2.13.0, released on April 11, 2024, resolved deserialization issues with immutable collections like ImmutableList and renamed internal classes (e.g., $Gson$Types to GsonTypes) for cleaner compatibility with tools and IDEs. The subsequent 2.13.2 release on September 10, 2025, refined Java Platform Module System (JPMS) declarations in the JAR for better modular application support and updated third-party dependencies to mitigate potential vulnerabilities. These changes build on prior improvements in generic handling and null safety while ensuring compatibility with Java 21.[6]
Maintenance of Gson is handled by Google via its official GitHub repository, which remains active with regular commits, security patches, and acceptance of community pull requests. Contributions from developers have driven many enhancements, such as those in generic and null handling. Support for legacy Java versions 6 and 7 has been deprecated since versions 2.9.0 and 2.12.0, respectively, with no further updates provided for them to prioritize modern environments.[1]
Core Functionality
Serialization Process
Gson's serialization process converts Java objects into JSON strings primarily through thetoJson method of the Gson class, which employs Java reflection to introspect and access the object's fields.[10] This reflection-based approach allows Gson to traverse the object's structure, including private fields, without requiring public getters or setters, making it straightforward for serializing plain old Java objects (POJOs).[10] By default, Gson includes all non-static, non-transient, and non-synthetic fields in the output, omitting any null-valued fields to produce a concise JSON representation.[10]
The library handles primitive types directly, mapping them to their JSON equivalents—for instance, an integer value serializes to a JSON number—while strings undergo automatic escaping of special characters such as quotes, backslashes, and control characters to ensure valid JSON syntax.[10] Arrays and collections, including those implementing Iterable or Map, are serialized as JSON arrays or objects, respectively; nested objects trigger recursive serialization to build hierarchical JSON structures.[10] Maps serialize with keys converted to strings via their toString() method, enabling complex key-value representations.[10]
Output formatting defaults to a compact, single-line JSON string for efficiency, but users can configure pretty-printed JSON—featuring indentation and line breaks—using the GsonBuilder class with the setPrettyPrinting() method before creating the Gson instance.[10] For error handling, Gson detects cyclic references during traversal and throws a StackOverflowError due to infinite recursion, preventing malformed output; unsupported types, such as certain custom classes without registered serializers, result in exceptions like JsonSerializationException.[10] This process contrasts with deserialization, which reconstructs objects from JSON strings.[11]
Deserialization Process
Gson's deserialization process involves parsing a JSON string or reader into a Java object using thefromJson method, which relies on reflection to map JSON elements to the corresponding Java types. The core mechanics begin with tokenization of the JSON input via the JsonReader class, which processes the document as a stream of tokens—such as begin object, name, string, number, and end object—in a depth-first traversal order to minimize memory consumption and support efficient handling of large or streaming data. This token stream is then traversed to construct the Java object graph, with each token mapped to appropriate Java primitives, objects, or collections based on the target type provided (either a Class or Type instance).[4]
To instantiate the target class, Gson invokes a default no-argument constructor (public or private) on the class, as it requires this mechanism to create an empty instance before populating its fields. Following instantiation, fields are set via reflection, where JSON property names are matched to Java field names by default, though this can be adjusted through naming policies configured in the GsonBuilder. This reflective field population supports direct assignment to non-final, non-static fields, ensuring the object's state aligns with the JSON structure. If the class lacks a no-args constructor, deserialization fails unless a custom InstanceCreator is registered to provide alternative instantiation logic.[4][12]
For generic types and collections, Gson performs type inference during mapping but encounters limitations due to Java's type erasure at runtime, necessitating the use of TypeToken to capture and convey the full parameterized type information—such as List<String>—to correctly deserialize nested or parameterized structures like arrays or maps. Without this, generics are treated as raw types, potentially leading to incorrect object creation. This approach ensures precise reconstruction of complex type hierarchies while maintaining compatibility with Java's type system.[4]
By default, Gson ignores unknown fields in the JSON input during deserialization, silently skipping them without affecting the resulting Java object, which promotes robustness when dealing with JSON from untrusted or evolving sources. This behavior can be refined through configuration options in GsonBuilder, such as exclusion strategies or the @Expose annotation, to selectively include or exclude fields, though no built-in strict mode enforces failure on unrecognized properties.[4]
Validation occurs throughout the process: malformed JSON syntax, such as invalid tokens or unbalanced structures, triggers a JsonSyntaxException, while type mismatches— like assigning a string to a numeric field—also raise this exception to halt deserialization and provide diagnostic details on the error location. This exception handling ensures type safety and alerts developers to structural discrepancies between the JSON and the target Java model.[4]
Usage
Basic Operations
Gson provides a straightforward API for basic serialization and deserialization tasks using its default configuration. To begin, instantiate a Gson object with the no-argument constructor, which applies the library's standard settings for handling most common Java types without additional customization.[10] For simple serialization, invoke thetoJson method on a Gson instance, passing a plain old Java object (POJO) as the argument; this converts the object into a JSON string representation. Consider a basic POJO such as the following:
public class User {
private String name;
private int age;
// Constructors, getters, and setters
public User(String name, int age) {
this.name = name;
this.age = age;
}
// ... (getters and setters omitted for brevity)
}
public class User {
private String name;
private int age;
// Constructors, getters, and setters
public User(String name, int age) {
this.name = name;
this.age = age;
}
// ... (getters and setters omitted for brevity)
}
User instance, serialization proceeds as:
Gson gson = new Gson();
User user = new User("Alice", 30);
String json = gson.toJson(user);
// Result: {"name":"Alice","age":30}
Gson gson = new Gson();
User user = new User("Alice", 30);
String json = gson.toJson(user);
// Result: {"name":"Alice","age":30}
fromJson method, specifying the target class for type-safe mapping. Continuing the example:
User deserializedUser = gson.fromJson(json, User.class);
// deserializedUser now holds the original values
User deserializedUser = gson.fromJson(json, User.class);
// deserializedUser now holds the original values
toJson directly serializes the array into a JSON array, and fromJson reconstructs it using the array class:
int[] numbers = {1, 2, 3};
String arrayJson = gson.toJson(numbers);
// Result: [1,2,3]
int[] deserializedArray = gson.fromJson(arrayJson, int[].class);
int[] numbers = {1, 2, 3};
String arrayJson = gson.toJson(numbers);
// Result: [1,2,3]
int[] deserializedArray = gson.fromJson(arrayJson, int[].class);
TypeToken to preserve type information, as Java erases generics at runtime:
import com.google.gson.reflect.TypeToken;
import [java.util.List](/page/List);
// Assuming json is '["apple","banana"]'
Type listType = new TypeToken<[List](/page/List)<[String](/page/String)>>(){}.getType();
[List](/page/List)<[String](/page/String)> fruits = gson.fromJson(json, listType);
import com.google.gson.reflect.TypeToken;
import [java.util.List](/page/List);
// Assuming json is '["apple","banana"]'
Type listType = new TypeToken<[List](/page/List)<[String](/page/String)>>(){}.getType();
[List](/page/List)<[String](/page/String)> fruits = gson.fromJson(json, listType);
fromJson calls in try-catch blocks to manage JsonParseException, which indicates parsing failures such as invalid syntax or type mismatches:
try {
User user = gson.fromJson(invalidJson, User.class);
} catch (JsonParseException e) {
// Handle error, e.g., log or provide user feedback
System.err.println("Invalid JSON: " + e.getMessage());
}
try {
User user = gson.fromJson(invalidJson, User.class);
} catch (JsonParseException e) {
// Handle error, e.g., log or provide user feedback
System.err.println("Invalid JSON: " + e.getMessage());
}
Configuration and Setup
To integrate Gson into a Java project, declare it as a dependency in the build configuration. For Maven, include the following in thepom.xml file:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.2</version>
</dependency>
build.gradle file:
implementation 'com.google.code.gson:gson:2.13.2'
implementation 'com.google.code.gson:gson:2.13.2'
GsonBuilder class to apply custom configurations, as the default new Gson() constructor provides only basic behavior.
To enable pretty-printing for readable JSON output with indentation and line breaks, invoke setPrettyPrinting() on the builder before creating the instance:
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
setLenient(true):
Gson gson = new GsonBuilder()
.setLenient()
.create();
Gson gson = new GsonBuilder()
.setLenient()
.create();
excludeFieldsWithoutExposeAnnotation(), which requires the @Expose annotation on desired fields:
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
setFieldNamingPolicy(), supporting policies like FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES for snake_case or FieldNamingPolicy.UPPER_CAMEL_CASE for PascalCase:
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
null values, enable serializeNulls():
Gson gson = new GsonBuilder()
.serializeNulls()
.create();
Gson gson = new GsonBuilder()
.serializeNulls()
.create();
registerTypeAdapter(Date.class, adapter) where the adapter implements JsonSerializer<Date> and/or JsonDeserializer<Date> to customize serialization to a specific string format, such as ISO 8601:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new CustomDateSerializer())
.create();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new CustomDateSerializer())
.create();
java.util.Date objects.[10]
Advanced Features
Custom Serialization and Deserialization
Gson provides mechanisms for customizing the serialization and deserialization of Java objects to and from JSON, particularly for types that do not have built-in support or require specific formatting. This is achieved by implementing adapter classes that handle the conversion logic for targeted types.[4] To define custom serialization, developers implement theJsonSerializer<T> interface, where T is the target type. The serialize method in this interface takes the object instance, its Type representation, and a JsonSerializationContext as parameters, returning a JsonElement that represents the desired JSON output. For deserialization, the JsonDeserializer<T> interface is used, with its deserialize method accepting a JsonElement, the target Type, and a JsonDeserializationContext, returning an instance of T. These interfaces allow precise control over the JSON structure for non-standard or complex types.[4]
A common use case is serializing Java 8's LocalDate to an ISO-8601 string format, such as "2023-10-15", instead of the default object representation. An adapter class, LocalDateAdapter, can implement both JsonSerializer<LocalDate> and JsonDeserializer<LocalDate>. In the serialize method, the LocalDate is converted to a string using toString() and wrapped in a JsonPrimitive. For deserialization, the JsonPrimitive is parsed as a string and converted back to LocalDate using LocalDate.parse(). This ensures consistent date handling in JSON.[4]
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.LocalDate;
public class LocalDateAdapter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDate.parse(json.getAsString());
}
}
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.LocalDate;
public class LocalDateAdapter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDate.parse(json.getAsString());
}
}
Gson instance using GsonBuilder. The registerTypeAdapter method associates the adapter with the specific type: Gson gson = new GsonBuilder().registerTypeAdapter(LocalDate.class, new LocalDateAdapter()).create(). This configuration applies the custom logic whenever LocalDate instances are encountered during serialization or deserialization.[4]
For enums, Gson defaults to serializing the enum constant's name as a string and deserializing by matching the JSON string to the enum's declared names. Custom handling can be implemented via a dedicated adapter using the JsonSerializer and JsonDeserializer interfaces to apply specific logic, such as ordinal-based serialization or fallback mappings. Alternatively, the @SerializedName annotation on enum constants can map alternative JSON values to enum instances without a full adapter.[4]
Tree-based processing offers low-level control for advanced scenarios, where JSON is parsed into a JsonElement tree using JsonParser. This allows manual traversal and modification of the JSON structure before final deserialization with Gson.fromJson(tree, targetClass) or during serialization by building custom JsonElement instances. Such an approach is useful for dynamic JSON manipulation without relying solely on type adapters.[4]
Handling Complex Data Types
Gson provides built-in mechanisms to manage serialization and deserialization of complex Java data structures, addressing challenges posed by Java's type erasure and object-oriented features. These include support for generics, nested and anonymous classes, interfaces, abstract classes, cyclic references, and polymorphic types. By leveraging classes likeTypeToken, InstanceCreator, and @Expose, along with factory utilities, developers can handle these scenarios without extensive custom code, though some require explicit configuration during Gson instance creation.[14]
Generic Type Handling
Java's type erasure at runtime obscures generic type information, preventing Gson from correctly deserializing collections likeList<String> when only the raw type List.class is provided. To resolve this, Gson introduces the TypeToken class, which captures the full generic type through anonymous subclassing, allowing preservation of type parameters during conversion.[14][15]
For example, to deserialize a JSON array of strings into a List<String>:
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> list = gson.fromJson(jsonString, listType);
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> list = gson.fromJson(jsonString, listType);
String elements rather than the default Object. Similarly, for nested generics like List<Foo<Bar>>, a TypeToken subclass defines the complete type hierarchy. Serialization of generics follows the same principle but is less affected by erasure, as the runtime type is available. Developers must register the TypeToken with the fromJson method for accurate results, a requirement stemming from Java's limitations rather than Gson's design.[14]
Nested and Anonymous Classes
Gson serializes static nested classes seamlessly, treating them as independent types during both serialization and deserialization. However, non-static (inner) nested classes, which implicitly hold references to their enclosing instance, require additional setup, as Gson lacks a default no-args constructor for instantiation. To enable this, developers must provide anInstanceCreator or refactor the class to static scope. Anonymous classes, often used for one-off implementations, are excluded by default and serialized as null, since their synthetic structure complicates reflection-based access.[14]
For inner classes, conversion to static nested classes is recommended for simplicity:
public static class StaticNestedClass {
// Fields and methods
}
public static class StaticNestedClass {
// Fields and methods
}
Interface and Abstract Class Mapping
Interfaces and abstract classes cannot be directly instantiated by Gson, as they lack concrete implementations. To map JSON to these types, anInstanceCreator must be registered with the GsonBuilder, supplying a strategy for creating instances of concrete subclasses during deserialization. This callback is invoked when Gson encounters the abstract type, allowing fields to be populated post-instantiation.[14][16]
Consider an interface Shape with implementations Circle and Square. An InstanceCreator<Shape> could default to Circle or use JSON metadata to select the subtype:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeHierarchyAdapter(Shape.class, new InstanceCreator<Shape>() {
public Shape createInstance(Type type) {
return new Circle(); // Default concrete instance
}
});
Gson gson = gsonBuilder.create();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeHierarchyAdapter(Shape.class, new InstanceCreator<Shape>() {
public Shape createInstance(Type type) {
return new Circle(); // Default concrete instance
}
});
Gson gson = gsonBuilder.create();
JsonIOException indicating uninstantiable types. This mechanism is essential for polymorphic hierarchies but requires careful subclass selection to avoid mismatches. Serialization of interfaces uses the runtime concrete type, ensuring fidelity.[14]
Cyclic References
Objects with bidirectional references, such as parent-child relationships in graphs, lead to infinite recursion in Gson's default serialization, as it traverses cycles without termination. Gson does not include built-in cycle detection; instead, prevention relies on annotations like@Expose to selectively include or exclude fields, breaking potential loops. By configuring the GsonBuilder to excludeFieldsWithoutExposeAnnotation(), only annotated fields are processed, allowing developers to omit back-references explicitly.[14][17]
For a Parent class referencing a Child that references back:
public class Parent {
@Expose Child child;
// No @Expose on parent field in Child to break cycle
}
public class Child {
Parent parent; // Excluded if using excludeFieldsWithoutExposeAnnotation
}
public class Parent {
@Expose Child child;
// No @Expose on parent field in Child to break cycle
}
public class Child {
Parent parent; // Excluded if using excludeFieldsWithoutExposeAnnotation
}
Polymorphic Types
For fields declared as base types but holding subclasses (e.g.,Animal with Dog or Cat instances), Gson requires runtime type discrimination to deserialize correctly. The RuntimeTypeAdapterFactory utility, available in Gson's codebase, registers subtypes with a label (e.g., a JSON field like "type": "dog"), enabling the factory to select the appropriate adapter based on that discriminator during parsing. This factory is constructed with the base type and label field, then populated with registerSubtype calls for each concrete class.
Example setup:
RuntimeTypeAdapterFactory<Animal> animalAdapterFactory = RuntimeTypeAdapterFactory.of(Animal.class, "type")
.registerSubtype([Dog](/page/Dog).class, "dog")
.registerSubtype([Cat](/page/Cat).class, "cat");
Gson gson = new GsonBuilder().registerTypeAdapterFactory(animalAdapterFactory).create();
RuntimeTypeAdapterFactory<Animal> animalAdapterFactory = RuntimeTypeAdapterFactory.of(Animal.class, "type")
.registerSubtype([Dog](/page/Dog).class, "dog")
.registerSubtype([Cat](/page/Cat).class, "cat");
Gson gson = new GsonBuilder().registerTypeAdapterFactory(animalAdapterFactory).create();
Performance and Alternatives
Performance Considerations
Gson relies on Java reflection to dynamically inspect and map object fields to JSON structures during serialization and deserialization, offering significant convenience for developers at the cost of performance overhead. This reflection mechanism, while enabling flexible handling of arbitrary Java types without custom code, incurs additional CPU cycles for field discovery and access compared to direct or pre-generated mapping approaches. As a result, Gson's processing speed is generally slower for large or complex objects, with benchmarks showing it can be up to 3 times slower than optimized alternatives for datasets involving thousands of elements in certain scenarios, such as on Android devices.[18][19] Gson's memory footprint remains low, particularly when leveraging its streaming API throughJsonReader and JsonWriter classes, which process JSON tokens sequentially rather than loading entire documents into memory. This approach is effective for handling payloads over 25 MB or collections exceeding 1.4 million objects during serialization and 87,000 during deserialization, as demonstrated in early internal benchmarks. By avoiding full in-memory representation, streaming mitigates out-of-memory errors and supports efficient processing of large-scale data without excessive garbage collection pressure.[4][20]
Several optimization strategies can mitigate Gson's performance bottlenecks. Reusing a single Gson instance across multiple operations is recommended, as instances are thread-safe and stateless, eliminating the overhead of repeated initialization and reflection caching. Disabling HTML escaping with GsonBuilder.disableHtmlEscaping() reduces unnecessary character transformations when JSON output is not destined for web contexts, thereby lowering serialization CPU costs. Additionally, annotating only relevant fields with @Expose and configuring the builder via excludeFieldsWithoutExposeAnnotation() limits reflection scans to essential members, accelerating field mapping for objects with many transient properties.[4][21][4]
Recent versions of Gson have incorporated targeted enhancements to address efficiency concerns. Benchmarks from independent evaluations on Java 17 confirm Gson's adequacy for moderate workloads, with deserialization throughput scaling reasonably for payloads up to 1 MB, though reflection limits its suitability for extreme high-throughput scenarios involving massive datasets. Independent benchmarks from 2024 on Java 17 show Gson performing adequately for moderate workloads, with deserialization suitable for payloads up to several MB, though slower than Jackson for high-throughput tasks. For such cases, the streaming API further bolsters scalability by enabling incremental processing.[22]
