我有一个多态数据类型,我试图将其直接反序列化为它的子类型(为了向后兼容),但如果没有类型信息,我无法反序列化,即使我在对象映射器上的 readValue
调用中直接引用子类型。我可以使用 jackson 魔法来解决这个问题吗?
class SerializationTest {
@Test
fun serializationTest() {
val serializedFoo = """ {"base":"blah", "foo": "something"} """
val foo = ObjectMapper().registerModule(KotlinModule()).readValue(serializedFoo, Foo::class.java)
println(foo)
}
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@JsonSubTypes(
JsonSubTypes.Type(value = Foo::class),
JsonSubTypes.Type(value = Bar::class)
)
internal abstract class Base {
abstract val base: String
}
internal class Foo(@JsonProperty("base") override val base: String,
@JsonProperty("foo") val foo: String): Base()
internal class Bar(@JsonProperty("base") override val base: String,
@JsonProperty("foo") val bar: String): Base()
}
失败
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.foo.bar.SerializationTest$Foo]: missing type id property '@class'
我目前使用的是 jackson 2.9.8
如果您可以在 objectmapper.readValue
中指定具体类,则可以使用 JsonTypeInfo.Id.NONE
。
为了完整起见,来自NONE
的javadoc:
This means that no explicit type metadata is included, and typing ispurely done using contextual information possibly augmented with other annotations.
这是一个 Java 测试用例:
public class SerializationTest {
@Test
public void serializationTest() throws JsonParseException, JsonMappingException, IOException {
final String json = getSerializedFoo();
final ObjectMapper om = getObjectMapper();
final Foo value = om.readValue(json, Foo.class);
assertTrue(value != null);
}
private ObjectMapper getObjectMapper() {
final ObjectMapper om = new ObjectMapper();
return om;
}
private String getSerializedFoo() {
return "{\"base\": \"blah\", \"foo\": \"something\"}";
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
@JsonSubTypes({
@Type(value = Foo.class),
@Type(value = Bar.class)
})
abstract class Base {
@JsonProperty("base")
protected String base;
public String getBase() {
return base;
}
public void setBase(final String base) {
this.base = base;
}
}
class Bar extends Base {
@JsonProperty("bar")
private String bar;
public String getBar() {
return bar;
}
public void setBar(final String foo) {
bar = foo;
}
}
class Foo extends Base {
@JsonProperty("foo")
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(final String foo) {
this.foo = foo;
}
}
我是一名优秀的程序员,十分优秀!