杰克逊的多态序列化/反序列化能力真的很酷,或者如果我能想出如何将其应用于我手边的问题。 http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html有一篇不错的文章,我无法适应我简化的问题。Jackson 2.1.2多态反序列化抛出JsonMappingException。为什么?
简而言之,我能够得到Jackson 2.1.2将一个类层次结构序列化成带有类型信息的JSON字符串。然而,我无法让Jackson 2.1.2将该JSON字符串反序列化为我的类层次结构。下面是一个揭示这个问题的单元测试。
类层次结构足够简单;只有两个直接子类的基类。此外,JSON输出似乎尊重我的杰克逊@JsonTypeInfo和mapper.writeValueAsString
{"type":"dog","name":"King","breed":"Collie"}
但我对mapper.readValue(jsonOfKing,Animal.class)调用产生一个可信的字符串踪迹......
FAILED: testJacksonSerializeDeserialize
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.rekdev.fasterjacksonwtf.PolymorphismTests$Dog]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: [email protected]; line: 1, column: 14]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:400)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
....
这是我的单元测试。
import org.testng.annotations.*;
import static org.testng.Assert.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.databind.*;
public class PolymorphismTests {
@Test
public void testJacksonSerializeDeserialize() throws Exception {
ObjectMapper mapper = new ObjectMapper();
Animal king = new Dog();
king.name = "King";
((Dog) king).breed = "Collie";
String jsonOfKing = mapper.writeValueAsString(king);
// JsonMappingException right here!
Animal actualKing = mapper.readValue(jsonOfKing, Animal.class);
assertEquals(king, actualKing);
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ @Type(value = Cat.class, name = "cat"), @Type(value = Dog.class, name = "dog") })
abstract class Animal {
public String name;
@Override
public abstract boolean equals(Object obj);
@Override
public abstract int hashCode();
}
class Dog extends Animal {
public String breed;
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Dog that = (Dog) obj;
boolean equals = name.equals(that.name) && breed.equals(that.breed);
return equals;
}
@Override
public int hashCode() {
int hashCode = name.hashCode() + breed.hashCode();
return hashCode;
}
}
class Cat extends Animal {
public String favoriteToy;
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Cat that = (Cat) obj;
boolean equals = name.equals(that.name) && favoriteToy.equals(that.favoriteToy);
return equals;
}
@Override
public int hashCode() {
int hashCode = name.hashCode() + favoriteToy.hashCode();
return hashCode;
}
}
}
为什么不ObjectMapper让我readValue过程中由ObjectMapper.writeValue产生的JSON()?
也许这里有一个线索:http://stackoverflow.com/questions/11798394/polymorphism-in-jackson-annotations-jsontypeinfo-usage。 “最不惊奇的原则”这种努力并非如此。 –
没有。并不那么简单。按下。 –
乍一看,我看到你在使用内部类的定义。这与我发布的例子不同。 –