Jackson反序列化泛型集合必须用TypeReference或JavaType,因Java类型擦除导致List.class无法保留元素类型,直接使用会得到List<LinkedHashMap>;TypeReference通过匿名子类保留泛型信息,JavaType适用于动态类型场景。

Java 中用 Jackson 反序列化带泛型的集合,不能直接写 List<User> 这样的类型,因为泛型在运行时被擦除,Jackson 无法知道具体元素类型。必须用 TypeReference 告诉它“这其实是一个 List<User>”。
为什么不能直接用 Class 类型?
像 objectMapper.readValue(json, List.class) 这样写,Jackson 只能解析出 List<LinkedHashMap> —— 所有元素都变成原始 Map,丢失了 User 类型信息。这是因为 Java 的类型擦除机制,List<User> 在运行时和 List<String> 都是同一个 List.class。
正确写法:用 TypeReference 包装泛型类型
把目标泛型类型封装进匿名子类,让 Jackson 能通过反射获取完整类型信息:
示例:反序列化 JSON 字符串为 List<User>
立即学习“Java免费学习笔记(深入)”;
- 定义好
User类(含 public 字段或 getter/setter) - 调用时传入
TypeReference<List<User>>() {{}}(注意双大括号语法是创建匿名子类) - 完整代码:
String json = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]";<br>
List<User> users = objectMapper.readValue(json, new TypeReference<List<User>>() {});
常见坑点和注意事项
- 双大括号里不能写逻辑(比如构造器语句),否则可能引发序列化问题或内存泄漏;只用来保留类型信息即可
- 如果泛型嵌套较深(如
Map<String, List<User>>),也要用TypeReference:new TypeReference<Map<String, List<User>>>() {} - 避免用
new TypeReference<List>() {}(没指定泛型参数),这和List.class效果一样,依然会丢失元素类型 - 确保
User类有无参构造方法,否则反序列化会失败
替代方案:使用 JavaType(适合动态类型场景)
如果类型在运行时才确定(比如从配置读取类名),可以用 JavaType 构造:
JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, User.class);<br> List<User> users = objectMapper.readValue(json, type);
这种方式更显式、可控,适合框架封装或泛型类型动态生成的场景。


















