Java中解析带泛型的JSON必须用TypeToken,因泛型类型擦除导致直接传List.class会反序列化为List;TypeToken通过匿名子类固化泛型信息,使Gson能识别完整类型如List。

Java中用Gson解析带泛型的JSON(比如 List<user></user>),不能直接传 List.class,否则反序列化出来的是 List<linkedtreemap></linkedtreemap>,运行时一取元素就抛 ClassCastException。根本原因在于Java泛型类型擦除——编译后 List<user></user> 和 List<string></string> 都只剩 List,Gson无法知道你要的是哪种。
为什么必须用 TypeToken>
TypeToken 是 Gson 提供的“类型占位器”,它通过匿名子类把泛型信息固化到字节码里,让 Gson 在运行时能读到完整类型,比如 List<user></user> 而不是模糊的 List。
- 错误写法(会出错):
gson.fromJson(json, List.class)→ 元素是LinkedTreeMap - 正确写法:
gson.fromJson(json, new TypeToken<list>>() {}.getType())</list>
基本用法:解析 List 类型
假设你有 JSON 字符串表示用户列表,对应实体类 User:
[{"id":1,"name":"张三"},{"id":2,"name":"李四"}]
解析代码如下:
立即学习“Java免费学习笔记(深入)”;
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
Gson gson = new Gson();
String json = "[{\"id\":1,\"name\":\"张三\"},{\"id\":2,\"name\":\"李四\"}]";
Type type = new TypeToken<List<User>>() {}.getType();
List<User> users = gson.fromJson(json, type); // ✅ 正确拿到 List<User>
处理嵌套泛型(如 Response>)
常见统一响应结构:
{"code":200,"message":"ok","data":[{"id":1,"name":"王五"}]}
对应类:
public class ApiResponse<T> {
int code;
String message;
T data;
}
解析时要一层层写出泛型:
Type type = new TypeToken<ApiResponse<List<User>>>() {}.getType();
ApiResponse<List<User>> response = gson.fromJson(json, type);
List<User> list = response.data; // ✅ 类型安全
封装通用解析方法(注意泛型擦除陷阱)
不能直接写 <t> List<t> parseList(String json)</t></t> 并在内部用 TypeToken<list>>()</list> —— 因为方法签名里的 T 在运行时已擦除,匿名子类捕获不到具体类型。
正确做法是传入 Class<t></t>,再逐个解析元素:
public static <T> List<T> parseList(String json, Class<T> clazz) {
JsonArray array = JsonParser.parseString(json).getAsJsonArray();
List<T> list = new ArrayList<>();
for (JsonElement elem : array) {
list.add(new Gson().fromJson(elem, clazz));
}
return list;
}
// 调用:List<User> users = parseList(jsonStr, User.class);

















