当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&lt;Object&gt;时,如果Object一个抽象类或接口,这里就会出现java多态的现象,比如,List&lt;Animal&gt;, 如果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&lt;MyBean&gt; result = mapper.readValue(src, new TypeReference&lt;List&lt;MyBean&gt;&gt;() { }); //如果是未知情况可以使用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()方法。