Everything Java

← Back to blog

Published on Tue Oct 07 2025 09:45:00 GMT+0000 (Coordinated Universal Time) by Purusothaman Ramanujam

Working with JSON Using Gson

Introduction

JSON (JavaScript Object Notation) has become the standard format for data exchange in modern applications. While Jackson is popular, Google’s Gson is another excellent library for JSON processing in Java. Gson is known for its simplicity, ease of use, and powerful features for converting Java objects to JSON and vice versa.

In this post, we’ll explore how to use Gson for JSON serialization and deserialization in Java applications.

What is Gson?

Gson is a Java library developed by Google that can be used to convert Java Objects into their JSON representation and vice versa. It provides:

Adding Gson to Your Project

Maven Dependency

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

Gradle Dependency

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

Basic Usage

Simple Object Serialization

Let’s start with a simple example:

import com.google.gson.Gson;
public class Person {
private String name;
private int age;
private String email;
// Constructors
public Person() {}
public Person(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
public class BasicGsonExample {
public static void main(String[] args) {
Gson gson = new Gson();
// Create a Person object
Person person = new Person("John Doe", 30, "john@example.com");
// Serialize to JSON
String json = gson.toJson(person);
System.out.println("Serialized JSON:");
System.out.println(json);
// Output: {"name":"John Doe","age":30,"email":"john@example.com"}
}
}

JSON Deserialization

Now let’s convert JSON back to a Java object:

public class DeserializationExample {
public static void main(String[] args) {
Gson gson = new Gson();
// JSON string
String json = "{\"name\":\"Jane Smith\",\"age\":25,\"email\":\"jane@example.com\"}";
// Deserialize JSON to Person object
Person person = gson.fromJson(json, Person.class);
System.out.println("Deserialized Person:");
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
System.out.println("Email: " + person.getEmail());
}
}

Working with Collections

Lists and Arrays

import java.util.List;
import java.util.Arrays;
public class CollectionExample {
public static void main(String[] args) {
Gson gson = new Gson();
// List of Person objects
List<Person> people = Arrays.asList(
new Person("Alice", 28, "alice@example.com"),
new Person("Bob", 32, "bob@example.com"),
new Person("Charlie", 35, "charlie@example.com")
);
// Serialize list to JSON
String json = gson.toJson(people);
System.out.println("Serialized List:");
System.out.println(json);
// Deserialize JSON array back to List
Type listType = new TypeToken<List<Person>>(){}.getType();
List<Person> deserializedPeople = gson.fromJson(json, listType);
System.out.println("\nDeserialized People:");
deserializedPeople.forEach(p ->
System.out.println(p.getName() + " - " + p.getAge()));
}
}

Maps

import java.util.HashMap;
import java.util.Map;
public class MapExample {
public static void main(String[] args) {
Gson gson = new Gson();
// Create a Map
Map<String, Object> data = new HashMap<>();
data.put("name", "John Doe");
data.put("age", 30);
data.put("active", true);
data.put("skills", Arrays.asList("Java", "Spring", "Gson"));
// Serialize Map to JSON
String json = gson.toJson(data);
System.out.println("Serialized Map:");
System.out.println(json);
// Deserialize JSON back to Map
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> deserializedData = gson.fromJson(json, mapType);
System.out.println("\nDeserialized Map:");
deserializedData.forEach((key, value) ->
System.out.println(key + ": " + value));
}
}

Custom Serialization and Deserialization

Using Annotations

Gson provides several annotations to customize serialization:

import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
public class User {
@SerializedName("user_name")
private String name;
@SerializedName("user_age")
private int age;
@Expose(serialize = false, deserialize = true)
private String password; // Won't be serialized, but can be deserialized
private String email; // Will be serialized as "email"
// Constructors, getters, setters
public User(String name, int age, String password, String email) {
this.name = name;
this.age = age;
this.password = password;
this.email = email;
}
// Getters and setters...
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}

Custom Serializers and Deserializers

You can create custom serializers and deserializers for complex scenarios:

import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class CustomSerializationExample {
// Custom serializer for LocalDate
public static class LocalDateSerializer implements JsonSerializer<LocalDate> {
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.format(DateTimeFormatter.ISO_LOCAL_DATE));
}
}
// Custom deserializer for LocalDate
public static class LocalDateDeserializer implements JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDate.parse(json.getAsString(), DateTimeFormatter.ISO_LOCAL_DATE);
}
}
public static void main(String[] args) {
// Create Gson with custom serializers
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer())
.create();
// Test with LocalDate
Event event = new Event("Meeting", LocalDate.now());
String json = gson.toJson(event);
System.out.println("Serialized: " + json);
Event deserializedEvent = gson.fromJson(json, Event.class);
System.out.println("Deserialized: " + deserializedEvent.getTitle() + " on " + deserializedEvent.getDate());
}
}
class Event {
private String title;
private LocalDate date;
public Event(String title, LocalDate date) {
this.title = title;
this.date = date;
}
// Getters and setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public LocalDate getDate() { return date; }
public void setDate(LocalDate date) { this.date = date; }
}

Gson Configuration

Custom Gson Builder

import com.google.gson.GsonBuilder;
public class GsonConfigurationExample {
public static void main(String[] args) {
// Create Gson with custom configuration
Gson gson = new GsonBuilder()
.setPrettyPrinting() // Pretty print JSON
.serializeNulls() // Include null values
.setDateFormat("yyyy-MM-dd HH:mm:ss") // Custom date format
.create();
Person person = new Person("John", 30, null); // email is null
String json = gson.toJson(person);
System.out.println("Pretty printed JSON:");
System.out.println(json);
}
}

Field Exclusion Strategies

public class ExclusionExample {
public static void main(String[] args) {
// Create Gson that excludes fields with @Expose(serialize = false)
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
User user = new User("John", 30, "secret123", "john@example.com");
String json = gson.toJson(user);
System.out.println("JSON without excluded fields:");
System.out.println(json);
// password field will be excluded
}
}

Working with Complex Objects

Nested Objects

public class ComplexObjectExample {
public static void main(String[] args) {
Gson gson = new Gson();
// Create complex object
Address address = new Address("123 Main St", "New York", "NY", "10001");
Employee employee = new Employee(1L, "John Doe", address, Arrays.asList("Java", "Spring"));
// Serialize
String json = gson.toJson(employee);
System.out.println("Complex object JSON:");
System.out.println(json);
// Deserialize
Employee deserializedEmployee = gson.fromJson(json, Employee.class);
System.out.println("\nDeserialized employee: " + deserializedEmployee.getName());
System.out.println("Address: " + deserializedEmployee.getAddress().getCity());
}
}
class Address {
private String street;
private String city;
private String state;
private String zipCode;
public Address(String street, String city, String state, String zipCode) {
this.street = street;
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
// Getters and setters
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getState() { return state; }
public void setState(String state) { this.state = state; }
public String getZipCode() { return zipCode; }
public void setZipCode(String zipCode) { this.zipCode = zipCode; }
}
class Employee {
private Long id;
private String name;
private Address address;
private List<String> skills;
public Employee(Long id, String name, Address address, List<String> skills) {
this.id = id;
this.name = name;
this.address = address;
this.skills = skills;
}
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public List<String> getSkills() { return skills; }
public void setSkills(List<String> skills) { this.skills = skills; }
}

Error Handling

Safe Deserialization

public class ErrorHandlingExample {
public static void main(String[] args) {
Gson gson = new Gson();
try {
// Invalid JSON
String invalidJson = "{\"name\":\"John\",\"age\":\"not_a_number\"}";
Person person = gson.fromJson(invalidJson, Person.class);
System.out.println("Person: " + person.getName());
} catch (JsonSyntaxException e) {
System.err.println("JSON syntax error: " + e.getMessage());
} catch (JsonParseException e) {
System.err.println("JSON parse error: " + e.getMessage());
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
}
}
}

Performance Considerations

Reusing Gson Instance

public class PerformanceExample {
// Create a single Gson instance to reuse
private static final Gson GSON = new Gson();
public static String toJson(Object obj) {
return GSON.toJson(obj);
}
public static <T> T fromJson(String json, Class<T> classOfT) {
return GSON.fromJson(json, classOfT);
}
public static void main(String[] args) {
Person person = new Person("John", 30, "john@example.com");
// Use the reusable Gson instance
String json = toJson(person);
Person deserialized = fromJson(json, Person.class);
System.out.println("Serialized and deserialized: " + deserialized.getName());
}
}

Best Practices

  1. Reuse Gson Instance: Create one Gson instance and reuse it for better performance.

  2. Use TypeToken for Generics: Use TypeToken when working with generic types.

  3. Handle Exceptions: Always wrap Gson operations in try-catch blocks.

  4. Use Annotations Sparingly: Only use annotations when necessary for customization.

  5. Validate Input: Always validate JSON input before processing.

  6. Consider Performance: For high-performance scenarios, consider using streaming APIs.

Common Pitfalls

  1. Type Erasure: Be careful with generic types; use TypeToken for complex generics.

  2. Circular References: Gson can handle circular references, but it’s better to avoid them.

  3. Null Handling: Be aware of how Gson handles null values in your configuration.

  4. Date Formatting: Always specify date formats explicitly for consistency.

  5. Field Visibility: Gson can access private fields, but consider using public getters/setters.

Conclusion

Gson is a powerful and user-friendly library for JSON processing in Java. Its simple API, excellent performance, and rich feature set make it an excellent choice for JSON serialization and deserialization.

In this post, we covered the basics of serialization, deserialization, working with collections, custom serializers, and best practices. As you become more comfortable with these concepts, you can explore advanced features like custom type adapters, exclusion strategies, and performance optimizations.

Resources

Written by Purusothaman Ramanujam

← Back to blog