傑克遜的多態序列化/反序列化能力真的很酷,或者如果我能想出如何將其應用於我手邊的問題。 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。 「最不驚奇的原則」這種努力並非如此。 –
沒有。並不那麼簡單。按下。 –
乍一看,我看到你在使用內部類的定義。這與我發佈的例子不同。 –