【TypeReference<目标泛型类型>】

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)); // 输出:篮球
}

三、关键细节(必看,避坑!)

  1. 必须加 {} :new TypeReference<...>() {} 末尾的大括号不能少!

    • 原理:TypeReference 是抽象类,{} 是创建匿名子类,子类会保留泛型的类型信息(绕过类型擦除)。
    • 错误写法:new TypeReference<List<String>>()(编译报错,抽象类不能直接实例化)。
  2. 泛型嵌套也能解析 :支持多层泛型,比如 TypeReference<Map<String, List<User>>>。

  3. 和直接传 Class 的区别:

    • JSON.parseObject(json, List.class) → 得到 List<Object>(丢失泛型)。
    • JSON.parseObject(json, new TypeReference<List<String>>() {}) → 得到 List<String>(保留泛型)。
  4. 处理 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);
}

总结

  1. 核心作用 :解决 Java 泛型擦除,让 FastJSON 能解析带泛型的对象(如 List<String>、ModelMessage<Map>)。
  2. 核心写法 :new TypeReference<目标泛型类型>() {}(末尾 {} 必须加)。
  3. 使用场景 :只要解析的目标类型包含泛型(非简单的 String/Integer/自定义普通类),就用 TypeReference,否则直接用 JSON.parseObject(json, 普通类.class) 即可。
相关推荐
默_笙5 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
rockmelodies5 天前
# Windows Server2008 R2 Standard(SP1镜像U盘)重置本地管理员密码【完整详细步骤】
windows·密码破解
qq_426003965 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫5 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技5 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读5 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时5 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
C语言小火车5 天前
C/C++ 为什么需要编译器?
开发语言·c++
奇思妙想聪明勤奋的小羊5 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型