接收JSON数据转换为Java对象时List<Data>字段映射报错问题
需要解析存储如下结构的JSON数据:
{ "api_status": 200, "data": [ {"id": "755", "post_id": "755", "publisher": { "username": "test1", "email": "test1@gmail.com"}}, {"id": "765","post_id": "765","publisher": { "username": "test2", "email": "test2@gmail.com"}} ] }
已创建3个对应Java实体类:
ModelPost.java
public class ModelPost { Integer api_status; List<Data> data; }
Data.java
public class Data { String id, post_id, postText; Publisher publisher; }
Publisher.java
public class Publisher { String username, email; }
当前异常表现:
ModelPost里data字段声明为List<Data>类型时,反序列化直接报错- 把类型改成
List<Object>(你写的Any是Kotlin类型,Java环境不存在)时能正常接收返回,但data里的内容没法自动映射为实体对象,只能拿到原始结构,无法直接操作实体属性。
核心是Java泛型擦除机制导致的:Java泛型只在编译期做类型校验,编译完成后JVM会擦除所有泛型参数信息,运行时根本不知道你List里装的是Data类型。JSON解析框架拿不到List内部的元素类型信息,自然没法把JSON数组里的对象自动转成Data实例,直接解析就会抛类型转换异常。
另外如果你的实体类没写无参构造、没给字段加getter/setter方法,也会直接导致反序列化失败,这是很容易漏的基础配置问题。
根据你用的JSON解析框架,选对应的写法即可,核心都是在解析时明确告诉框架泛型的实际类型:
用Fastjson的场景
解析时不要直接传ModelPost.class,用TypeReference携带完整泛型信息:
String json = "待解析的原始JSON字符串"; ModelPost result = JSON.parseObject(json, new TypeReference<ModelPost>(){}); // 此时拿到的data就是正常映射完成的List<Data>,内部publisher字段也会自动映射 List<Data> postList = result.getData();
嫌手写getter/setter、无参构造麻烦的话,直接给三个实体类都加上Lombok的@Data注解就行,会自动生成这些方法。
用Jackson的场景
逻辑和Fastjson一致,通过TypeReference指定泛型:
ObjectMapper mapper = new ObjectMapper(); ModelPost result = mapper.readValue(json, new TypeReference<ModelPost>(){});
如果后续要做下划线命名转驼峰(比如把post_id自动映射到postId字段),加一行配置即可,你当前字段名和JSON字段完全一致,不配也能正常用:
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
用Gson的场景
用TypeToken传递泛型类型信息:
Gson gson = new Gson(); ModelPost result = gson.fromJson(json, new TypeToken<ModelPost>(){}.getType());
用List<Object>接收时,框架默认会把JSON对象解析成LinkedHashMap结构,不是字符串,你如果硬要这么写也可以手动把Map转成Data实体,但远不如上面直接指定泛型的写法高效。
另外注意:如果你给实体类加了带参数的构造方法,一定要手动补一个无参构造,JSON框架反序列化时默认要调用无参构造创建对象实例,缺了就会报错。
内容的提问来源于stack exchange,提问作者sss

