【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) 即可。
相关推荐
格鸰爱童话2 小时前
向AI学习项目技能(三)
java·人工智能·python·学习
阿蒙Amon2 小时前
C#常用类库-详解Log4Net
开发语言·c#
datalover2 小时前
golang实现kms
开发语言·golang·iphone
Leo⁵2 小时前
通过DrissionPage爬取boss直聘,绕过__zp_stoken__解析
爬虫·python·自动化
爱打代码的小林2 小时前
识别盒装图标项目的一些功能函数
python·pycharm
小邓睡不饱耶2 小时前
基于Python的Q房网二手房数据爬虫实现
开发语言·爬虫·python
在屏幕前出油2 小时前
00. FastAPI——了解FastAPI
后端·python·pycharm·fastapi
深蓝电商API2 小时前
爬虫任务调度:APScheduler 定时执行
开发语言·爬虫·python