Fastjson 1 泛型与 TypeReference
在做Java项目开发的时候,你在使用 Fastjson 1 时一定遇到过这样的情况:明明写对了 JSON 字符串,解析后却得到了意想不到的结果,甚至抛出异常。这通常是因为没有正确处理泛型信息。现在介绍Fastjson 1 中的泛型解析利器 TypeReference。
为什么需要 TypeReference?
Java 的泛型在运行时会被擦除(Type Erasure)。例如 List<User> 在运行时只会被当成 List 处理,失去了 User 的类型信息。当你用 JSON.parseObject(json, List.class) 时,Fastjson 并不知道列表里装的是什么类型,只能默认转换为 JSONObject 或 JSONArray。
看一个典型错误例子:
String json = "[{\"name\":\"张三\"}, {\"name\":\"李四\"}]";
List<User> users = JSON.parseObject(json, List.class);
List userList = JSON.parseObject(json, List.class); // 编译通过,但运行使用时报错
for (User user: userList) {
System.out.println(user.getName());
}
这里编译没有问题,但运行后 users 里的元素其实是 JSONObject,不是 User,报错信息为 Exception in thread "main" java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.example.domain.User
TypeReference 介绍
TypeReference 是 Fastjson 提供的一个抽象类,用于在运行时保留泛型类型信息。它的用法是:创建一个匿名内部类,通过子类来捕获父类的泛型参数。
基本语法
import com.alibaba.fastjson.TypeReference;
// 保留 List<User> 的类型信息
TypeReference<List<User>> typeRef = new TypeReference<List<User>>() {};
List<User> users = JSON.parseObject(json, typeRef);
注意:new TypeReference<List<User>>() {} 末尾的 {} 一定要有,表示创建匿名子类。
实战示例
解析泛型 List
public class User {
public String name;
public int age;
}
public class Demo {
public static void main(String[] args) {
String json = "[{\"name\":\"Tom\",\"age\":25},{\"name\":\"Jerry\",\"age\":23}]";
// 错误方式:泛型信息丢失
List list = JSON.parseObject(json, List.class);
Object first = list.get(0);
System.out.println(first.getClass()); // class com.alibaba.fastjson.JSONObject
// 正确方式:使用 TypeReference
List<User> users = JSON.parseObject(json,
new TypeReference<List<User>>() {});
User user = users.get(0);
System.out.println(user.name); // Tom
System.out.println(user.getClass()); // class User
}
}
解析复杂嵌套泛型
比如 Map<String, List<Integer>> 这种类型:
String json = "{\"scores\":[90,85,92],\"grades\":[95,88]}";
Map<String, List<Integer>> map = JSON.parseObject(json,
new TypeReference<Map<String, List<Integer>>>() {});
System.out.println(map.get("scores").get(0)); // 90
解析api数据的例子
String resultJson = "{\"code\":200,\"data\":[{\"name\":\"Tom\",\"age\":25}]}";
// 定义泛型类
class Result<T> {
public int code;
public T data;
}
// 正确解析方式
Result<List<User>> result = JSON.parseObject(resultJson,
new TypeReference<Result<List<User>>>() {});
System.out.println(result.data.get(0).name); // Tom
作为方法参数传递
当你封装工具方法时,TypeReference 非常有用:
public static <T> T parseGeneric(String json, TypeReference<T> typeRef) {
return JSON.parseObject(json, typeRef);
}
// 调用
List<User> users = parseGeneric(json, new TypeReference<List<User>>() {});
背后的原理
Fastjson 通过 TypeReference 的 getType() 方法获取到完整的泛型类型(例如 java.util.List<com.example.User>),从而在反序列化时知道如何处理内部元素。这个技巧利用了 Java 匿名内部类在编译时会记录父类泛型信息的特性。
常见误区
- 忘记写
{}:new TypeReference<List<User>>()是错误的,必须写{}才能创建匿名子类。 - 类型写错:TypeReference 的泛型参数必须与实际 JSON 结构完全匹配。
- 混用 parseObject 的重载:
parseObject(String, Class)用于无泛型场景,有泛型时必须使用TypeReference版本。
总结
记住一个简单原则:只要 JSON 中包含泛型信息(如 List、Map 或自定义泛型类),就使用 TypeReference 来保留类型。这不仅能避免运行时的 ClassCastException,还能让你的代码更健壮、更易维护。

