当json包含type属性时,jackson能否确定要反序列化的根对象类型?

时间:2015-02-07 16:05:26

标签: java json jackson

假设序列化到json包含实际对象的类名,在类上使用此注释:

@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);

实际上不起作用,它会带回一张地图。

4 个答案:

答案 0 :(得分:7)

嗯,我当然可以这样做,尽管我个人从未使用过杰克逊。您可以将其反序列化为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的

答案 1 :(得分:2)

是的,但有一个警告:您必须提供的类型包括您指定的@JsonTypeInfo。除非您使用“混合注释”来关联它,否则Object.class将不会有。

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

答案 2 :(得分:2)

    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);

这应该有效并且非常方便。

答案 3 :(得分:2)