当 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
是的,但有一个警告:您输入的类型必须包含您指定的 @JsonTypeInfo
。 Object.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);
这应该可以,而且非常方便。
假设 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
是的,但有一个警告:您输入的类型必须包含您指定的 @JsonTypeInfo
。 Object.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);
这应该可以,而且非常方便。