接口返回一个数组字符串,代码里写了把 JSON 解析结果转成 List 的强转,编译过得去,取第一个元素时抛 ClassCastException,说 JSONObject 不能转成 User。
能强转,是因为它本来就实现了 List
fastjson 的 JSONArray 实现了 List 接口,所以加个原始类型强转编译器不会拦。但里面装的是 JSONObject,不是你的实体类。泛型在运行时被擦除,编译器管不到元素类型,问题就留到取值那一刻才爆出来。
正确写法只有一行
拿到 JSONArray 之后调 toJavaList,把目标类的 class 传进去,元素就都是实体对象了。手上是字符串的话,先 parseArray 再转,或者直接用带 class 参数的静态方法一步到位。
array.toJavaList(User.class)JSONArray.parseArray(text, User.class)
Jackson 和 Gson 的写法不一样
Jackson 要用 TypeReference 保留泛型信息,末尾那对空花括号不能少。Gson 用 TypeToken,同样要写匿名子类。三者共同的坑是:直接传 List.class 进去,元素会变成 LinkedHashMap,取属性时又是一次类型错误,报错信息还更难看懂。
日期和空字段最容易翻车
实体里有 LocalDateTime 的,fastjson 1.x 默认可能解析失败,要配日期格式或者升到 2.x。字段名和 JSON 里的键不一致时加注解映射。值为 null 的键默认会被丢掉,业务上要区分「没有这个字段」和「值为空」,得打开对应的序列化特性。
嵌套数组别一层层强转
数组里套数组的返回,外层转成实体类后,内层的 List 字段已经是实体列表,不用再手动转。如果实体里那个字段声明成了 Object,取出来仍然是 JSONArray,这时候在 getter 里做一次转换更稳,别在每个调用点各写一遍。
结论:别做原始类型强转,一律走带 class 参数的转换方法,泛型信息才保得住。