当 json 包含类型 属性 时,jackson 可以确定要反序列化到的根对象类型吗?

Can jackson determine root object type to deserialize to when json includes type property?

假设 json 的序列化包括实际对象的 class 名称,在 Class:

上使用此注释
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type")
class MyClass {
    String foo;
}

所以 json 例如:

{"@type": "com.example.MyClass", "foo": "bar"}

可以在不指定类型的情况下反序列化吗?我的意思是甚至不是超级类型。就像:

objectMapper.readValue(value, Object.class);

这实际上不起作用,它带回了一个地图。

嗯,这当然是可能的,尽管我个人从未那样使用过 Jackson。您可以将其反序列化为 JsonNode 对象,然后将其转换为正确的类型。

final ObjectMapper objectMapper = new ObjectMapper();
final MyClass myClass = new MyClass();
myClass.foo = "bar";

// Serialize
final String json = objectMapper.writeValueAsString(myClass);

// Deserialize
final JsonNode jsonNode = objectMapper.readTree(json);

// Get the @type
final String type = jsonNode.get("@type").asText();

// Create a Class-object
final Class<?> cls = Class.forName(type);

// And convert it
final Object o = objectMapper.convertValue(jsonNode, cls);

System.out.println(o.getClass());

输出为:

MyClass

是的,但有一个警告:您输入的类型必须包含您指定的 @JsonTypeInfoObject.class不会有,除非你用"mix-in annotations"来关联它。

但是,如果您需要为 java.lang.Object 的(声明类型)的属性添加类型信息,您可能希望启用默认类型:有关详细信息,请参阅 ObjectMapper.enableDefaultTyping(...)。 这实际上将允许包含(和使用)更大类别的类型信息 类,而无需添加注释。

    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

    MyClass original = new MyClass();
    original.foo = "hello";

    String json = mapper.writeValueAsString(original);
    MyClass foo = (MyClass) mapper.readValue(json, MyClass.class);

这应该可以,而且非常方便。

您要使用的是Jackson Polymorphic Deserialization