我有一个名为 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/