【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) 即可。
相关推荐
2301_816660217 分钟前
CSS中relative与absolute的区别_详解相对与绝对定位应用场景
jvm·数据库·python
qq_4609784016 分钟前
Golang怎么JWT设置过期时间_Golang如何在Claims中配置Token有效期【操作】
jvm·数据库·python
weixin_5689960619 分钟前
Cgo 中正确设置 C 结构体回调函数指针的完整方案
jvm·数据库·python
Jun62619 分钟前
【RV1103】AD4115实现8通道ADC采样,MQTT数据传输,1K采样率
linux·python
橘颂TA29 分钟前
【Linux】自旋锁
linux·开发语言·数据库·c++
LiAo_1996_Y31 分钟前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
一诺加油鸭34 分钟前
若依后端系统集成 Swagger 接口文档功能
java·开发语言
ECT-OS-JiuHuaShan34 分钟前
功夫不负匠心人,渡劫代谢舞沧桑
android·开发语言·人工智能·算法·机器学习·kotlin·拓扑学
knight_9___35 分钟前
LLM工具调用面试篇1
开发语言·人工智能·python·面试·agent
2601_9561394235 分钟前
快消品品牌全案公司哪家强
大数据·人工智能·python