泛型解析失败本质是Java类型擦除导致运行时泛型信息缺失,需用TypeToken(Gson)或TypeReference(Fastjson)通过匿名子类保留类型签名,显式传递完整参数化类型如List或Result,嵌套泛型同理,动态类型需构造并缓存Type,结构不确定时优先用Map保全字段完整性。

泛型解析失败,本质不是库的问题,而是 Java 编译期擦除导致运行时类型信息缺失。Fastjson 和 Gson 都无法凭空知道 List<user></user> 里的 User 是什么——必须靠你显式告诉它。
用 TypeReference(Fastjson)或 TypeToken(Gson)补全泛型信息
这是最直接、最通用的解法。它们利用匿名内部类在字节码中保留泛型签名的特性,让 JSON 库能在运行时拿到完整类型结构。
-
Fastjson 示例:不要写
JSON.parseObject(json, List.class),改用:List<user> users = JSON.parseObject(json, new TypeReference<list>>() {});</list></user> -
Gson 示例:避免
gson.fromJson(json, List.class),应写:Type type = new TypeToken<list>>() {}.getType();<br> List<user> users = gson.fromJson(json, type);</user></list> - 嵌套泛型也一样适用,比如
ApiResponse<page>></page>:new TypeReference<apiresponse>>>() {}</apiresponse>(Fastjson)
或new TypeToken<apiresponse>>>() {}.getType()</apiresponse>(Gson)
统一响应体(如 Result)必须传完整参数化类型
很多项目封装了类似 Result<user></user> 的返回结构,但若只传 Result.class,data 字段会变成 LinkedTreeMap,强转必报 ClassCastException。
- 错误写法:
Result<user> r = gson.fromJson(json, Result.class);</user> - 正确写法(Gson):
Result<user> r = gson.fromJson(json, new TypeToken<result>>() {}.getType());</result></user> - 正确写法(Fastjson):
Result<user> r = JSON.parseObject(json, new TypeReference<result>>() {});</result></user> - 如果 T 是动态的(比如运行时才知道是 User 还是 Order),需构造 Type 并缓存,避免重复反射开销
不确定结构的 JSON:用 Map + TypeReference 保字段完整性
当接口返回的 JSON 结构不固定(可能是 A 类或 B 类),又不想定义一堆 POJO,直接解析为 JSONObject 容易丢字段(比如 null 值被跳过、顺序错乱、嵌套 map 被扁平化)。
- 推荐方式:
Map<string object> data = JSON.parseObject(json, new TypeReference<map object>>() {});</map></string> - 这样能完整保留所有 key、null 值、嵌套层级;后续可按需提取字段或转成具体对象
- 若后续要转成某个实体类,可用
JSON.toJSONString(data)再反解析,避免中间丢失
精度与类型不匹配问题:别依赖自动转换
数值精度丢失(如 "price":10.5 解析进 int price 变成 10)不是泛型问题,但常和泛型场景一起出现。
- 方案一:字段类型对齐,把
int price改成BigDecimal或Double - 方案二:Fastjson 开启严格模式或自定义 ParserFeature(如
Feature.UseBigDecimal) - 方案三:Gson 注册自定义
JsonDeserializer<long></long>或JsonDeserializer<number></number>,统一处理数字解析逻辑











