TypeReference 是 FastJSON(阿里)提供的核心工具类,专门解决 Java 泛型类型擦除 问题,让 JSON 解析时能正确识别泛型(比如 List<User>、ModelMessage<Map>),而不是解析成原始的 Object。
一、先理解核心痛点:为什么需要 TypeReference?
Java 泛型是"编译时有效,运行时擦除"的------比如 List<String> 运行时会变成 List,直接用 JSON.parseObject(json, List.class) 解析,得到的是 List<Object>,而非 List<String>。
TypeReference 的作用就是保存泛型的真实类型信息,让 FastJSON 能精准解析出带泛型的对象。
二、TypeReference 基础用法(从易到难)
1. 最简写法(JDK 8+ 支持菱形语法)
java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.List;
import java.util.Map;
public class TypeReferenceDemo {
public static void main(String[] args) {
// 示例1:解析简单泛型(List<String>)
String json1 = "[\"Java\",\"FastJSON\",\"TypeReference\"]";
// 核心写法:new TypeReference<目标泛型类型>() {}
List<String> strList = JSON.parseObject(
json1,
new TypeReference<List<String>>() {} // 注意末尾的 {},必须加!
);
System.out.println(strList.get(0)); // 输出:Java(类型是 String,而非 Object)
// 示例2:解析嵌套泛型(Map<String, Integer>)
String json2 = "{\"age\":25,\"score\":98}";
Map<String, Integer> intMap = JSON.parseObject(
json2,
new TypeReference<Map<String, Integer>>() {}
);
System.out.println(intMap.get("age") + 1); // 输出:26(Integer 可直接运算)
}
}
2. 解析自定义泛型类(比如ModelMessage)
假设自定义泛型类是:
java
// 自定义泛型类
class ModelMessage<T> {
private ModelHeader header;
private T body; // 泛型 body,可能是 Map、String、List 等
// 省略 getter/setter
public ModelHeader getHeader() { return header; }
public void setHeader(ModelHeader header) { this.header = header; }
public T getBody() { return body; }
public void setBody(T body) { this.body = body; }
}
// 辅助类
class ModelHeader {
private String requestId;
private String timestamp;
// 省略 getter/setter
}
用 TypeReference 解析 ModelMessage<Map<String, Object>>:
java
public class CustomGenericDemo {
public static void main(String[] args) {
// 模拟你的 JSON 数据
String json = "{\"header\":{\"requestId\":\"123\",\"timestamp\":\"20260313\"},\"body\":{\"name\":\"张三\",\"age\":25}}";
// 关键:指定完整泛型类型 ModelMessage<Map<String, Object>>
TypeReference<ModelMessage<Map<String, Object>>> typeRef =
new TypeReference<ModelMessage<Map<String, Object>>>() {};
// 解析后直接得到带泛型的对象
ModelMessage<Map<String, Object>> message = JSON.parseObject(json, typeRef);
// 直接使用,无需手动类型转换
System.out.println(message.getHeader().getRequestId()); // 输出:123
System.out.println(message.getBody().get("name")); // 输出:张三
System.out.println(message.getBody().get("age")); // 输出:25(类型是 Integer)
}
}
3. 进阶:动态指定泛型类型(可选)
如果泛型类型需要动态调整(比如有时是 Map,有时是 List),可以封装成方法:
java
// 通用解析方法
public static <T> T parseJson(String json, TypeReference<T> typeRef) {
return JSON.parseObject(json, typeRef);
}
// 调用示例
public static void main(String[] args) {
String json = "{\"header\":{},\"body\":[\"篮球\",\"读书\"]}";
// 解析 body 为 List<String> 的情况
ModelMessage<List<String>> message = parseJson(
json,
new TypeReference<ModelMessage<List<String>>>() {}
);
System.out.println(message.getBody().get(0)); // 输出:篮球
}
三、关键细节(必看,避坑!)
-
必须加
{}:new TypeReference<...>() {}末尾的大括号不能少!- 原理:
TypeReference是抽象类,{}是创建匿名子类,子类会保留泛型的类型信息(绕过类型擦除)。 - 错误写法:
new TypeReference<List<String>>()(编译报错,抽象类不能直接实例化)。
- 原理:
-
泛型嵌套也能解析 :支持多层泛型,比如
TypeReference<Map<String, List<User>>>。 -
和直接传 Class 的区别:
JSON.parseObject(json, List.class)→ 得到List<Object>(丢失泛型)。JSON.parseObject(json, new TypeReference<List<String>>() {})→ 得到List<String>(保留泛型)。
-
处理 null 值 :如果 JSON 字段是
null(比如你之前的{"entities":null,"text":null}),解析后对应字段也是null,不会报错,可通过if (xxx != null)安全判断。
四、实战场景(对应你的需求)
针对你之前的 {"entities":null,"text":null},用 TypeReference 解析:
java
// 假设你的目标类型是 ModelMessage<Map<String, Object>>
String yourJson = "{\"header\":null,\"body\":{\"entities\":null,\"text\":null}}";
TypeReference<ModelMessage<Map<String, Object>>> typeRef =
new TypeReference<ModelMessage<Map<String, Object>>>() {};
ModelMessage<Map<String, Object>> message = JSON.parseObject(yourJson, typeRef);
// 安全取值(避免 null 空指针)
Map<String, Object> body = message.getBody();
if (body != null) {
Object entities = body.get("entities"); // null
Object text = body.get("text"); // null
System.out.println("entities: " + entities + ", text: " + text);
}
总结
- 核心作用 :解决 Java 泛型擦除,让 FastJSON 能解析带泛型的对象(如
List<String>、ModelMessage<Map>)。 - 核心写法 :
new TypeReference<目标泛型类型>() {}(末尾{}必须加)。 - 使用场景 :只要解析的目标类型包含泛型(非简单的
String/Integer/自定义普通类),就用TypeReference,否则直接用JSON.parseObject(json, 普通类.class)即可。