Java泛型擦除导致JSON反序列化多层泛型失败,解决关键是显式传递完整泛型类型:用TypeReference(通用)或ParameterizedTypeReference(Jackson专用),并升级Fastjson2至2.0.51+。

Java 泛型在 JSON 转实体类时遇到多层泛型(比如 Result<Page<UserDto>>),核心难点是运行时泛型信息被擦除,导致反序列化器无法知道 records 里该转成 UserDto 还是 JSONObject。这不是 JSON 库的 bug,而是 Java 语言机制决定的。解决的关键在于显式传递带完整泛型路径的类型信息。
用 TypeReference 显式保留泛型结构
这是最通用、兼容性最好的方式,适用于 Fastjson2、Jackson、Gson 等主流库。
- 不要直接传
Result.class—— 它只包含顶层类型,Page<UserDto>和UserDto全丢了 - 要创建匿名子类:
new TypeReference<Result<Page<UserDto>>>() {} - 调用时传入
typeRef.getType()(Fastjson2/Jackson)或直接传typeRef(Gson) - 示例(Fastjson2):
TypeReference<Result<Page<UserDto>>> typeRef = new TypeReference<Result<Page<UserDto>>>() {};
Result<Page<UserDto>> result = JSON.parseObject(json, typeRef.getType());
升级 Fastjson2 到 2.0.51+ 版本
旧版 Fastjson2(及所有 Fastjson1)对嵌套泛型支持较弱,容易把 records: [...] 解析成 JSONArray 而非 List<UserDto>。
- 2.0.51 起显著增强泛型推导能力,配合
TypeReference更稳定 - 注意检查项目中是否混用了 fastjson1 和 fastjson2,二者不兼容
- 若用 Maven,确认依赖坐标为:
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.51</version>
避免内部类 + 使用扁平 DTO(适合简单场景)
如果只是临时解析、不需复用泛型逻辑,可绕过泛型擦除问题,改用“字段扁平化”DTO。
立即学习“Java免费学习笔记(深入)”;
- 例如原 JSON 是
{"code":200,"data":{"total":10,"records":[{"id":1,"name":"Alice"}]}} - 不定义
Page<T>类,而定义一个ApiResponse类,把records直接声明为List<UserDto> - 再配合
@JsonProperty("data.records")(Jackson)或@SerializedName("data.records")(Gson)做路径映射 - 优点:无泛型擦除风险,调试直观;缺点:丧失类型复用性,JSON 结构变动时 DTO 需同步调整
Jackson 用户可用 ParameterizedTypeReference
如果你用的是 Jackson(ObjectMapper),推荐使用它原生的 ParameterizedTypeReference,语义更清晰且无需匿名类。
- 写法:
ParameterizedTypeReference<Result<Page<UserDto>>> typeRef =
new ParameterizedTypeReference<Result<Page<UserDto>>>() {};
Result<Page<UserDto>> result = objectMapper.readValue(json, typeRef); - 比
TypeReference更安全,不会因字节码优化导致类型丢失 - 要求 Jackson 版本 ≥ 2.12(推荐 2.15+)


















