W3docs

Java JSON with Gson

Parse and serialize JSON in Java with Google's Gson library — toJson, fromJson, and TypeToken.

Java JSON with Gson

JSON is the lingua franca of modern web APIs, and Java applications constantly need to turn objects into JSON and parse JSON back into objects. Gson is Google's open-source library for exactly this: a small, dependency-free toolkit that maps Java objects to JSON text and back with almost no boilerplate. This chapter shows how Gson works and the patterns you will reach for every day.

Adding Gson to Your Project

Gson is not part of the JDK, so you add it as a dependency. With Maven you declare it in your pom.xml:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

With Gradle the same dependency is a single line:

implementation 'com.google.code.gson:gson:2.11.0'

Everything you do with Gson goes through a single entry-point class, Gson. You normally create one instance and reuse it — it is thread-safe and cheap to share.

import com.google.gson.Gson;

Gson gson = new Gson();

Serializing Objects to JSON

Turning a Java object into JSON text is called serialization, and Gson does it with toJson(). You hand it any object and Gson walks its fields using reflection, producing a JSON string. No annotations or configuration are required for ordinary classes.

class Book {
    String title;
    String author;
    int year;
    boolean inStock;

    Book(String title, String author, int year, boolean inStock) {
        this.title = title;
        this.author = author;
        this.year = year;
        this.inStock = inStock;
    }
}

Gson gson = new Gson();
Book b = new Book("Clean Code", "Robert Martin", 2008, true);
String json = gson.toJson(b);
// {"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}

Field names become JSON keys, and Java types map to the natural JSON types: String to a quoted string, int/double to a number, boolean to true/false. A null field is omitted by default.

Deserializing JSON to Objects

The reverse direction — deserialization — uses fromJson(). You pass the JSON text and the target Class, and Gson creates an instance and fills in the fields by matching JSON keys to field names.

String json = "{\"title\":\"Clean Code\",\"author\":\"Robert Martin\",\"year\":2008,\"inStock\":true}";

Gson gson = new Gson();
Book b = gson.fromJson(json, Book.class);

System.out.println(b.title);  // Clean Code
System.out.println(b.year);   // 2008

If a JSON key has no matching field, Gson ignores it; if a field has no matching key, it is left at its default value (null, 0, or false). This forgiving behavior makes Gson resilient when an API adds new fields.

TypeToken for Generic Collections

Java erases generic type information at runtime, so gson.fromJson(json, List.class) cannot know that you want a List<Book> — it would hand back a List of LinkedTreeMap objects. Gson solves this with TypeToken, which captures the full generic type so deserialization produces the elements you expect.

import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;

String json = "[{\"title\":\"Effective Java\",\"year\":2018}]";

Type listType = new TypeToken<List<Book>>(){}.getType();
List<Book> books = gson.fromJson(json, listType);

Use a TypeToken whenever the target type involves generics — List<T>, Map<K, V>, or nested combinations. For plain, non-generic classes, the simple Book.class form is enough.

Pretty Printing and Custom Configuration

The default Gson produces compact, single-line JSON. To configure behavior you build an instance with GsonBuilder. The most common request is pretty printing — human-readable, indented output for logs and config files.

import com.google.gson.GsonBuilder;

Gson gson = new GsonBuilder()
        .setPrettyPrinting()
        .serializeNulls()        // include null fields instead of dropping them
        .create();

System.out.println(gson.toJson(b));

GsonBuilder controls many other behaviors. A few you will meet often:

Builder methodEffect
setPrettyPrinting()Indented, multi-line output
serializeNulls()Emit null fields instead of skipping them
setDateFormat(...)Control how Date values are formatted
registerTypeAdapter(...)Plug in a custom serializer/deserializer for a type
excludeFieldsWithoutExposeAnnotation()Only serialize fields marked @Expose

For full control over one type, you register a custom adapter implementing JsonSerializer and/or JsonDeserializer — useful when a field needs special formatting that reflection cannot infer.

A Worked Example: Serialize, Parse, and Round-Trip

Gson itself is not on this runner's classpath, so the program below demonstrates the same concepts using only the JDK: it serializes a record to JSON by hand, parses the text back into fields, rebuilds the object, and confirms the round-trip is lossless. This is exactly what gson.toJson() and gson.fromJson() automate for you.

java— editable, runs on the server

What to take from the run:

  • The first line shows serialization: the Book record becomes {"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}, where each field is a JSON key and types map to their natural JSON forms — exactly what gson.toJson() produces.
  • The second line shows deserialization: parsing that text back and rebuilding a Book, the same job gson.fromJson(json, Book.class) does in one call.
  • Round-trip equal? true proves the conversion is lossless — serializing then deserializing yields an object equal to the original, the property every JSON mapper aims for.
  • The Array JSON line shows a List<Book> rendered as a JSON array of objects, the structure you would deserialize with a TypeToken<List<Book>>.
  • The Pretty block shows indented, multi-line output, illustrating what GsonBuilder.setPrettyPrinting() gives you compared to the compact default.

Practice

Practice

In Gson, why do you need a TypeToken to deserialize a List<Book> instead of just passing List.class?