> For the complete documentation index, see [llms.txt](https://wisdom.gitbook.io/gyan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wisdom.gitbook.io/gyan/java/gson/type-token.md).

# Type Token

```
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
```

### Problem That TypeToken solves

```java
// Consider these two lists
List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();

// At runtime, due to type erasure, Java sees both as just List
// This means we can't directly tell Gson what type to deserialize to

// with the help of TypeToken we tell Gson about type of data in process of ser and desr.

// Creating a TypeToken for a List of Strings
Type listType = new TypeToken<List<String>>(){}.getType();

// Using it with Gson
List<String> strings = gson.fromJson(jsonString, listType);
```

### Different Ways to Use TypeToken

1. **Simple Generic Types**

```java
// For List<String>
Type stringListType = new TypeToken<List<String>>(){}.getType();

// For Set<Integer>
Type integerSetType = new TypeToken<Set<Integer>>(){}.getType();

// For Map<String, Boolean>
Type mapType = new TypeToken<Map<String, Boolean>>(){}.getType();
```

2. **Nested Generic Types**

```java
// For List<List<String>>
Type nestedListType = new TypeToken<List<List<String>>>(){}.getType();

// For Map<String, List<User>>
Type complexMapType = new TypeToken<Map<String, List<User>>>(){}.getType();
```

3. **Custom Generic Classes**

```java
// Generic response wrapper
public class ApiResponse<T> {
    private int status;
    private T data;
    // getters and setters
}

// Usage
Type responseType = new TypeToken<ApiResponse<User>>(){}.getType();
ApiResponse<User> response = gson.fromJson(json, responseType);
```

### Creating Reusable TypeTokens

```java
public class TypeTokens {
    // Private constructor to prevent instantiation
    private TypeTokens() {}
    
    // Reusable TypeToken for List<String>
    public static final Type STRING_LIST_TYPE = new TypeToken<List<String>>(){}.getType();
    
    // Reusable TypeToken for Map<String, User>
    public static final Type STRING_USER_MAP_TYPE = new TypeToken<Map<String, User>>(){}.getType();
}

// Usage
List<String> strings = gson.fromJson(json, TypeTokens.STRING_LIST_TYPE);
```

### Advanced Usage with Parameterized Types

```java
public class GenericTypeHandler<T> {
    private final Type type;

    public GenericTypeHandler() {
        // Capture the actual type parameter
        Type superclass = getClass().getGenericSuperclass();
        if (superclass instanceof ParameterizedType) {
            this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
        } else {
            throw new RuntimeException("Missing type parameter.");
        }
    }

    public T fromJson(String json) {
        return new Gson().fromJson(json, type);
    }
}

// Usage
public class UserListHandler extends GenericTypeHandler<List<User>> {}

UserListHandler handler = new UserListHandler();
List<User> users = handler.fromJson(jsonString);
```

### Working with Complex Nested Structures

```java
public class ComplexTypeExample {
    public static void main(String[] args) {
        Gson gson = new Gson();
        
        // Complex nested structure
        Type complexType = new TypeToken<Map<String, List<Set<User>>>>(){}.getType();
        
        // Creating sample data
        Map<String, List<Set<User>>> data = new HashMap<>();
        // ... populate data ...
        
        // Serialization
        String json = gson.toJson(data, complexType);
        
        // Deserialization
        Map<String, List<Set<User>>> parsed = gson.fromJson(json, complexType);
    }
}
```

### Some points to consider -

1. Insure proper type safety.
2. Do proper error handling.
3. Create type tokens and reuse them.
