【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) 即可。
相关推荐
z落落6 小时前
C# 泛型方法(原理、类型推断、多泛型参数)+泛型效率(普通类型 VS Object装箱 VS 泛型)
开发语言·c#
L_09076 小时前
【C++】异常
开发语言·c++
世辰辰辰7 小时前
批量修改图片/文本名子
开发语言·python·批量修改文件名
myenjoy_19 小时前
MQTT 与 Sparkplug B——从车间到云端的最后一公里
网络·python
z落落9 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
caimouse10 小时前
Reactos 第 4 章 对象管理 — 4.5 几个常用的内核函数
c语言·windows·架构
VidDown10 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
装不满的克莱因瓶10 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
颜酱10 小时前
LangChain 输出解析器:把模型回复变成你要的数据
python·langchain
2401_8734794010 小时前
企业安全运营中,如何用IP离线库提前发现失陷主机?三步实现风险画像
网络·数据库·python·tcp/ip·ip