接口返回的是一串 JSON 数组,我用 Gson 直接 fromJson 想转成 List,跑起来就抛 ClassCastException,说 LinkedTreeMap 不能转成 User。第一次碰这问题的基本都卡在这儿。

直接传 List.class 为什么会崩

Gson 靠泛型信息反序列化。你写 fromJson(json, List.class),编译后泛型被擦除了,它只知道要建个 List,不知道里面装什么,于是默认给你塞 LinkedTreeMap。等到取值时强转 User 就炸了。

正式写法用 TypeToken

正确姿势是拿匿名子类把泛型带过去:

Type type = new TypeToken<List<User>>(){}.getType();
List<User> list = new Gson().fromJson(json, type);

这里的花括号 {} 是关键,少了它泛型照样丢。Kotlin 里换 TypeToken 也可以用 object 表达式,本质上都是给编译器留一个带泛型的类型。

实体字段名对不上时的两种办法

  • 字段名和 JSON 不一致:在字段上标 SerializedName
  • 所有字段都想换成下划线风格:建 Gson 时设 FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES
  • 要忽略多余字段:默认就忽略,反过来想严格校验要自己配
  • 时间字段:用 setDateFormat 指定格式,否则按默认解析

嵌套 List 与泛型类

如果实体里还有 List 字段,TypeToken 一样能写:

new TypeToken<Result<List<User>>>(){}.getType()

外层是包装类 Result,里面套数组,一层层照写就行。真要动态反射,TypeToken 用不了,得上 TypeAdapter 或者 JsonDeserializer 自己解析。

记牢一点:Gson 解析集合一律用 TypeToken,别图快写 List.class,这是百分之九十的报错来源。数据量大、还想省内存,就换 JsonReader 流式读。