当java对象中含List<Object>时,如果Object一个抽象类或接口,这里就会出现java多态的现象,比如List<Animal>, 如果Animal是个抽象类,并且有多个子类时,由于List中保存的Animal没有明确指向具体的子类或实现类,json反序列化java对象时就会抛出提示:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException:Can not construct instance of Animal, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
可以使用@JsonTypeInfo与@JsonSubTypes来解决此类问题,通过注解,可以在序列化时,保存具体的类型信息到json中,当json反序列到java对象时,就可以根据具体类型信息创建正确的java对象。
@JsonTypeInfo – indicates details of what type information to include in serialization 指出序列化包含的类型信息细节
@JsonSubTypes – indicates sub-types of the annotated type 指出被注解类型的子类
@JsonTypeName – defines a logical type name to use for annotated class 定义被注解类使用的逻辑名称
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
public class Animal {
public String name;
public Animal(String name) {
@JsonTypeName("dog")
// 这里在子类中指定的type name必须和抽象类中注解@JsonSubTypes中name属性指定的值保持一致
public class Dog extends Animal {
public double barkVolume;
public Dog(String name) {
super(name);
barkVolume = 0.5;
@JsonTypeName("cat")
public class Cat extends Animal {
boolean likesCream;
public int lives;
public Cat(String name) {
super(name);
likesCream = true;
lives = 10;
@Test
public void whenSerializingPolymorphic_thenCorrect()
throws JsonProcessingException {
Zoo.Dog dog = new Zoo.Dog("lacy");
Zoo zoo = new Zoo(dog);
String result = new ObjectMapper()
.writeValueAsString(zoo);
assertThat(result, containsString("type"));
assertThat(result, containsString("dog"));
序列化zoo对象,结果如下:
"type":"dog",
"name":"lacy",
"barkVolume":0
@Test
public void whenDeserializingPolymorphic_thenCorrect()
throws IOException {
String json = "{\"name\":\"lacy\",\"type\":\"cat\"}";
Animal animal =
new ObjectMapper().readerFor(Animal.class).readValue(json);
assertEquals("lacy", animal.name);
assertEquals(Cat.class, animal.getClass());
当java对象中含List<Object>时,如果Object一个抽象类或接口,这里就会出现java多态的现象,比如,List<Animal>, 如果Animal是个抽象类,并且有多个子类时,由于List中保存的Animal没有明确指向具体的子类或实现类,json反序列化java对象时就会抛出提示:Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException:Can ...
抽象类:
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
接口(英文:
Java接口和Java抽象类代表的是抽象类型,是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为你结构层次上的顶层。
1、Java接口和Java抽象类大的一个区别,在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以,这大概是Java抽象类的优点吧,但这个优点非常有用。 如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个新方法,所有实现这
现在有这样的需求:
在controller接口层,@RequestBody接收的是抽象类,@ResponseBody也是抽象类。controller根据请求参数反序列化成子类对象,返回时返回子类对象。
MongoDB在新增数据时使用的是抽象类,查询返回结果也是抽象类。
默认情况,抽象类是无法完成序列化和反序列化的。那怎么实现呢?
现在有这样的类结果:
//如果已知想要序列化的类型 可以使用TypeReference来进行处理
//List result = mapper.readValue(src, new TypeReference() { });
//如果是未知情况可以使用TypeFactory来进行动态反射序列化
//apper.readValue(src, TypeFactory.defa...
//如果已知想要序列化的类型 可以使用TypeReference来进行处理
//List<MyBean> result = mapper.readValue(src, new TypeReference<List<MyBean>>() { });
//如果是未知情况可以使用TypeFactory来进行动态反射序列化
//apper.readVa...
自定义序列化器需要继承 JsonSerializer<T>; 接口,泛型为需要被序列化的对象
重写 serialize() 方法
在需要序列化的实体类上加上注解 @JsonSerialize(using = TemplateSerialize.class) 指定序列化器
public class TemplateSerialize extends JsonSerializer<...
1.定义一个抽象类:使用关键字abstract定义一个类,这个类不能被实例化,只能被继承。
2.定义抽象方法:使用关键字abstract定义一个方法,这个方法没有方法体,只有方法的声明。
3.子类继承抽象类:子类通过extends关键字继承抽象类,并且必须实现抽象类中的所有抽象方法。
以下是一个简单的抽象类的例子:
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
abstract void makeSound();
class Dog extends Animal {
public Dog(String name) {
super(name);
@Override
void makeSound() {
System.out.println(name + " is barking");
class Cat extends Animal {
public Cat(String name) {
super(name);
@Override
void makeSound() {
System.out.println(name + " is meowing");
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("Buddy");
Animal cat = new Cat("Fluffy");
dog.makeSound();
cat.makeSound();
在这个例子中,Animal类是一个抽象类,它有一个抽象方法makeSound(),这个方法没有方法体。Dog和Cat类继承Animal类,并且实现了makeSound()方法。在Main类中,我们创建了一个Dog对象和一个Cat对象,并且调用它们的makeSound()方法。因为Dog和Cat类实现了Animal类的抽象方法,所以它们可以被实例化并调用makeSound()方法。