Gson
Json
ArrayList
Java
Data Conversion

Gson - convert from Json to a typed ArrayListT

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Gson is Google's Java library for converting between JSON and Java objects. To deserialize a JSON array into a typed ArrayList<T>, you need TypeToken because Java's type erasure removes generic type information at runtime. Without TypeToken, Gson cannot determine that you want an ArrayList<Person> instead of an ArrayList<Object>. The pattern is: create a TypeToken capturing the full generic type, pass its getType() to gson.fromJson(), and Gson correctly deserializes each array element into the specified type.

Basic Deserialization with TypeToken

java
1import com.google.gson.Gson;
2import com.google.gson.reflect.TypeToken;
3import java.lang.reflect.Type;
4import java.util.ArrayList;
5import java.util.List;
6
7public class Main {
8    public static void main(String[] args) {
9        Gson gson = new Gson();
10
11        String json = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]";
12
13        // TypeToken captures the generic type ArrayList<Person>
14        Type listType = new TypeToken<ArrayList<Person>>(){}.getType();
15        ArrayList<Person> people = gson.fromJson(json, listType);
16
17        for (Person p : people) {
18            System.out.println(p.getName() + " is " + p.getAge());
19        }
20        // Alice is 30
21        // Bob is 25
22    }
23}
24
25class Person {
26    private String name;
27    private int age;
28
29    // Getters and setters
30    public String getName() { return name; }
31    public void setName(String name) { this.name = name; }
32    public int getAge() { return age; }
33    public void setAge(int age) { this.age = age; }
34}

The new TypeToken<ArrayList<Person>>(){} syntax creates an anonymous subclass that preserves the generic type through reflection — working around Java's type erasure.

Why TypeToken Is Needed

java
1Gson gson = new Gson();
2String json = "[{\"name\":\"Alice\"},{\"name\":\"Bob\"}]";
3
4// WRONG — returns ArrayList<LinkedTreeMap>, not ArrayList<Person>
5ArrayList list = gson.fromJson(json, ArrayList.class);
6System.out.println(list.get(0).getClass());
7// com.google.gson.internal.LinkedTreeMap
8
9// CORRECT — returns ArrayList<Person>
10Type type = new TypeToken<ArrayList<Person>>(){}.getType();
11ArrayList<Person> people = gson.fromJson(json, type);
12System.out.println(people.get(0).getClass());
13// Person

Without TypeToken, Gson does not know the element type and defaults to its internal map representation.

Different Collection Types

java
1Gson gson = new Gson();
2String json = "[1, 2, 3, 4, 5]";
3
4// ArrayList<Integer>
5Type intListType = new TypeToken<ArrayList<Integer>>(){}.getType();
6ArrayList<Integer> intList = gson.fromJson(json, intListType);
7
8// LinkedList<Integer>
9Type linkedType = new TypeToken<LinkedList<Integer>>(){}.getType();
10LinkedList<Integer> linkedList = gson.fromJson(json, linkedType);
11
12// List<Integer> (interface — Gson uses ArrayList)
13Type listType = new TypeToken<List<Integer>>(){}.getType();
14List<Integer> list = gson.fromJson(json, listType);
15
16// Set<Integer> (removes duplicates)
17String jsonDups = "[1, 2, 2, 3, 3, 3]";
18Type setType = new TypeToken<HashSet<Integer>>(){}.getType();
19Set<Integer> set = gson.fromJson(jsonDups, setType);
20System.out.println(set);  // [1, 2, 3]

Nested Generic Types

java
1// List of lists
2String json = "[[1,2,3],[4,5,6],[7,8,9]]";
3Type nestedType = new TypeToken<ArrayList<ArrayList<Integer>>>(){}.getType();
4ArrayList<ArrayList<Integer>> matrix = gson.fromJson(json, nestedType);
5System.out.println(matrix.get(1).get(2));  // 6
6
7// Map inside a list
8String mapJson = "[{\"key\":\"a\",\"value\":1},{\"key\":\"b\",\"value\":2}]";
9Type mapListType = new TypeToken<ArrayList<Map<String, Object>>>(){}.getType();
10ArrayList<Map<String, Object>> mapList = gson.fromJson(mapJson, mapListType);

Serialization (ArrayList to JSON)

java
1Gson gson = new Gson();
2
3ArrayList<Person> people = new ArrayList<>();
4people.add(new Person("Alice", 30));
5people.add(new Person("Bob", 25));
6
7// Serialization does not need TypeToken
8String json = gson.toJson(people);
9System.out.println(json);
10// [{"name":"Alice","age":30},{"name":"Bob","age":25}]
11
12// Pretty printing
13Gson prettyGson = new GsonBuilder().setPrettyPrinting().create();
14System.out.println(prettyGson.toJson(people));

Generic Helper Method

java
1public class JsonHelper {
2    private static final Gson gson = new Gson();
3
4    public static <T> ArrayList<T> fromJsonArray(String json, Class<T> clazz) {
5        Type type = TypeToken.getParameterized(ArrayList.class, clazz).getType();
6        return gson.fromJson(json, type);
7    }
8
9    public static <T> String toJson(List<T> list) {
10        return gson.toJson(list);
11    }
12}
13
14// Usage
15ArrayList<Person> people = JsonHelper.fromJsonArray(json, Person.class);
16ArrayList<Integer> numbers = JsonHelper.fromJsonArray("[1,2,3]", Integer.class);

TypeToken.getParameterized() (Gson 2.8+) creates the type programmatically, avoiding the anonymous subclass syntax.

Custom Deserializer

java
1import com.google.gson.*;
2import java.lang.reflect.Type;
3
4public class PersonDeserializer implements JsonDeserializer<Person> {
5    @Override
6    public Person deserialize(JsonElement json, Type typeOfT,
7                               JsonDeserializationContext context) throws JsonParseException {
8        JsonObject obj = json.getAsJsonObject();
9        String name = obj.get("name").getAsString();
10        int age = obj.has("age") ? obj.get("age").getAsInt() : 0;
11        return new Person(name, age);
12    }
13}
14
15// Register
16Gson gson = new GsonBuilder()
17    .registerTypeAdapter(Person.class, new PersonDeserializer())
18    .create();
19
20Type listType = new TypeToken<ArrayList<Person>>(){}.getType();
21ArrayList<Person> people = gson.fromJson(json, listType);

Handling null and Empty Arrays

java
1Gson gson = new Gson();
2Type type = new TypeToken<ArrayList<Person>>(){}.getType();
3
4// Empty array
5ArrayList<Person> empty = gson.fromJson("[]", type);
6System.out.println(empty.size());  // 0
7
8// null JSON
9ArrayList<Person> nullResult = gson.fromJson("null", type);
10System.out.println(nullResult);  // null
11
12// Safe handling
13ArrayList<Person> safe = gson.fromJson(json, type);
14if (safe == null) safe = new ArrayList<>();

Common Pitfalls

  • Omitting TypeToken and getting LinkedTreeMap instead of your POJO: Without TypeToken, gson.fromJson(json, ArrayList.class) deserializes objects as LinkedTreeMap, not your target class. Always use new TypeToken<ArrayList<YourClass>>(){}.getType().
  • Reusing a raw Type variable across different generic types: Each TypeToken is specific to one parameterized type. Creating new TypeToken<ArrayList<Person>>(){}.getType() and using it for ArrayList<Order> silently produces wrong results.
  • Missing a no-arg constructor on the target class: Gson creates instances using the no-arg constructor by default. If Person only has a parameterized constructor, deserialization fails with RuntimeException. Add a no-arg constructor or register a custom InstanceCreator.
  • Field name mismatches between JSON and Java: Gson maps JSON keys to Java field names by exact match. If JSON uses "first_name" but the Java field is firstName, the field is null. Use @SerializedName("first_name") to map the names.
  • Not handling null values in JSON arrays: JSON arrays can contain null elements ([{"name":"Alice"},null,{"name":"Bob"}]). Iterating without null checks causes NullPointerException. Filter or check for null elements after deserialization.

Summary

  • Use new TypeToken<ArrayList<T>>(){}.getType() to capture the generic type for Gson deserialization
  • Without TypeToken, Gson deserializes JSON objects as LinkedTreeMap instead of your target class
  • Use TypeToken.getParameterized(ArrayList.class, MyClass.class) (Gson 2.8+) for programmatic type creation
  • Serialization (toJson) does not need TypeToken — Gson inspects the runtime types automatically
  • Always provide a no-arg constructor on target classes and use @SerializedName for JSON key mapping

Course illustration
Course illustration

All Rights Reserved.