jackson反序列化泛型集合必须用typereference或javatype,因java类型擦除导致list.class无法保留元素类型,直接使用会得到list;typereference通过匿名子类保留泛型信息,javatype适用于动态类型场景。

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











