java - 缺少属性 'type',而映射的反序列化包含混合子类型 - 多态性

标签 java json jackson hashmap polymorphism

我有一个名为 Animal 的对象,它有两个子类,Monkey 和 Lion,我使用 JsonTypeInfo 来支持子类型检测,我想在序列化 JsonTypeInfo 时应该根据类自动放置名为“type”的属性.

动物类

import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Lion.class, name = "Lion"),
        @JsonSubTypes.Type(value = Monkey.class, name = "Monkey")
})
public class Animal implements Serializable {
    
    String name;

    public Animal(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Animal other = (Animal) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

狮子类


public class Lion extends Animal{

    public Lion(String name) {
        super(name);
    }

}


猴类


public class Monkey extends Animal{

    public Monkey(String name) {
        super(name);
    }

}

主要功能

    public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
        Map<String,Animal> animals = new HashMap<String, Animal>();
        animals.put("Bob", new Lion("Bob"));
        animals.put("Alice", new Monkey("Alice"));
        StringWriter sw = new StringWriter();
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_NULL);
        mapper.writeValue(sw, animals);
        String animlasStr = sw.toString();
        Map<String,Animal> dAnimalMap = mapper.readValue(animlasStr, new TypeReference<Map<String, Animal>>() {});
        assert dAnimalMap.get("Alice") instanceof Monkey;
    }

但是当我反序列化动物 map 时它不起作用!!,它抛出以下异常,type 属性丢失。

 com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id  (for class ....Animal)
 at [Source: {"Bob":{"name":"Bob"},"Alice":{"name":"Alice"}}

我尝试了类型引用和可见属性,我得到了相同的结果。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type" , visible =true)

最佳答案

代替: mapper.writeValue(sw, animals); 采用 mapper.writerFor(new TypeReference<Map<String, ? extends Animal>>() {}).writeValue(sw, animals);

而不是: mapper.readValue(animlasStr, new TypeReference<Map<String, Animal>>() {}); 采用: mapper.readValue(animlasStr, new TypeReference<Map<String, ? extends Animal>>() {});

所有类中的构造函数都是空的

关于java - 缺少属性 'type',而映射的反序列化包含混合子类型 - 多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62615492/

相关文章:

java - RichFaces - 组合框中包含字母或组合的建议

java - 无法将 ArrayList 数据加载到 android 中的微调器

java - 使用 Jackson 解析数组

java - jackson 未处理的异常?

java - 使用B类对象创建B类对象

java - 逐行读取文本文件并将这些行插入到输出文件上的 -d= 序列之后

Python 无法更新 JSON 字符串的坐标

json - 在 Golang 中将表单值分配给结构

java - 直接 self 引用导致循环 Ebean 和 Jackson

java - 如何定期更新 xml 文件?