java泛型擦除导致json反序列化多层泛型失败,解决关键是显式传递完整泛型类型:用typereference(通用)或parameterizedtypereference(jackson专用),并升级fastjson2至2.0.51+。

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











