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:
- Simple API: Easy to use with minimal configuration
- Flexible: Supports custom serializers and deserializers
- Type Safety: Handles complex object hierarchies
- Performance: Fast and memory-efficient
- Annotation Support: Customize serialization behavior
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
-
Reuse Gson Instance: Create one Gson instance and reuse it for better performance.
-
Use TypeToken for Generics: Use
TypeTokenwhen working with generic types. -
Handle Exceptions: Always wrap Gson operations in try-catch blocks.
-
Use Annotations Sparingly: Only use annotations when necessary for customization.
-
Validate Input: Always validate JSON input before processing.
-
Consider Performance: For high-performance scenarios, consider using streaming APIs.
Common Pitfalls
-
Type Erasure: Be careful with generic types; use
TypeTokenfor complex generics. -
Circular References: Gson can handle circular references, but it’s better to avoid them.
-
Null Handling: Be aware of how Gson handles null values in your configuration.
-
Date Formatting: Always specify date formats explicitly for consistency.
-
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