仅通过修改Person类添加Jackson注解实现混合类型无泛型List的正确反序列化
仅通过修改Person类添加Jackson注解实现混合类型无泛型List的正确反序列化
嘿,这个问题我太熟悉了!你碰到的核心问题是:当反序列化无泛型声明的List时,Jackson没法知道列表里的对象具体是什么类型,所以默认把JSON对象转成了LinkedHashMap,这就导致后面强转Person时抛出ClassCastException。
好消息是,完全可以只通过给Person类添加Jackson注解来解决,不用修改你的测试代码,也不用开启全局默认类型。下面是具体方案:
解决方案:给Person类添加@JsonTypeInfo注解
我们可以让Jackson在序列化Person对象时,自动把类的类型信息写入JSON中;反序列化时,Jackson就能通过这个类型信息识别出该节点要转成Person对象,而不是LinkedHashMap。
修改后的Person类代码如下:
import com.fasterxml.jackson.annotation.JsonTypeInfo; public static class Person { private String name; private String surname; // 核心注解:序列化时写入类的全限定名作为类型标识 @JsonTypeInfo( use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class" // 自定义类型属性名,你也可以改成"type"之类的 ) public Person() { // 必须保留无参构造器,Jackson反序列化时需要用到 } public Person(String name, String surname) { this.name = name; this.surname = surname; } // 别忘了添加Getters和Setters public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } }
为什么这个方案可行?
- 序列化阶段:当你把List转成JSON时,Person对象会被额外加上一个
@class属性,值是Person类的全限定名(比如de.mpg.ipp.codac.archivedb.restapi.JsonTestsPlayground$Person),而Integer 23这类基本类型不受影响。 - 反序列化阶段:Jackson读到带有
@class属性的JSON节点时,会自动根据这个属性值找到对应的Person类,把JSON转成Person实例,而不是默认的LinkedHashMap。
注意事项
- 必须保留Person类的无参构造器:Jackson在反序列化对象时,默认会调用无参构造器来创建实例。
- 如果你不想用类的全限定名作为类型标识,也可以把
use改成JsonTypeInfo.Id.NAME,然后配合@JsonSubTypes注解给Person指定一个别名,不过用Id.CLASS更直接,不需要额外配置别名,适合你这种没有父类的场景。
这样修改之后,你的测试代码就能正常运行,outList.get(1)反序列化出来的就是Person对象,强转时不会再抛出异常啦!
备注:内容来源于stack exchange,提问作者primož perušek
相关产品推荐
相关产品推荐

