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); // 2008If 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 method | Effect |
|---|---|
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.
What to take from the run:
- The first line shows serialization: the
Bookrecord 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 whatgson.toJson()produces. - The second line shows deserialization: parsing that text back and rebuilding a
Book, the same jobgson.fromJson(json, Book.class)does in one call. Round-trip equal? trueproves the conversion is lossless — serializing then deserializing yields an object equal to the original, the property every JSON mapper aims for.- The
Array JSONline shows aList<Book>rendered as a JSON array of objects, the structure you would deserialize with aTypeToken<List<Book>>. - The
Prettyblock shows indented, multi-line output, illustrating whatGsonBuilder.setPrettyPrinting()gives you compared to the compact default.
Practice
In Gson, why do you need a TypeToken to deserialize a List<Book> instead of just passing List.class?