【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) 即可。
相关推荐
love530love5 小时前
OpenClaw Windows Companion 桌面客户端 连接 LM Studio 完整配置指南
人工智能·windows·python·openclaw
程序喵大人7 小时前
【C++进阶】STL容器与迭代器 - 01 STL 容器先解决元素放在哪里
开发语言·c++·stl
cui_ruicheng7 小时前
Python从入门到实战(十六):多进程编程
开发语言·python
wdfk_prog9 小时前
嵌入式面试真题第 15 题:不可恢复异常后的通用崩溃快照、调用栈保存与离线分析架构
linux·开发语言·面试·架构
_Jimmy_9 小时前
FastAPI + SQLAlchemy全局事务管理
python·fastapi
晴空了无痕9 小时前
从 Go 基础到 K8s:一条可落地的 Go 服务端成长路线
开发语言·后端·golang·kubernetes
用户8356290780519 小时前
如何使用 Python 在 Excel 中添加、编辑和删除超链接
后端·python
神明不懂浪漫9 小时前
【第五章】Java中的继承与多态
java·开发语言
神州世通10 小时前
解密企业通信安全防线:Avaya Aura 三层安全架构深度解析
开发语言·php
AC赳赳老秦11 小时前
企业工商公开信息采集分析:OpenClaw 批量查询企业工商信息,生成企业画像报告
大数据·开发语言·python·自动化·php·deepseek·openclaw