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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28384281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:30:11  来源:igfitidea点击:

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

javajsonHymanson

提问by Nazaret K.

Assume serialization to json includes the class name of the actual object, using this annotation on the Class:

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

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type")
class MyClass {
    String foo;
}

So json is for example:

所以 json 是例如:

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

Can this be deserialized without specifying the type? And I mean not even the super type. Just something like:

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

objectMapper.readValue(value, Object.class);

which doesn't actually work, it brings back a Map.

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

采纳答案by wassgren

Well, it is certainly possible to do that although I have personally never used Hymanson that way. You can deserialize it to a JsonNodeobject and then convert it to the proper type.

好吧,虽然我个人从未那样使用过Hyman逊,但当然可以这样做。您可以将其反序列化为一个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());

The output is:

输出是:

MyClass

我的课

回答by sydraz

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

This should work and is very convenient.

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

回答by Farrukh Najmi

回答by StaxMan

Yes, but there is a caveat: type you give MUST be something that includes @JsonTypeInfoyou specify. Object.classwill not have, unless you use "mix-in annotations" to associate it.

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

However, if you need to add type information for properties of (declared type of) java.lang.Object, you probably want to enable default typing: see ObjectMapper.enableDefaultTyping(...)for more information. That will actually enable inclusion (and use) of type information for larger categories of classes, without need to add annotations.

但是,如果您需要为 (declared type of) 的属性添加类型信息java.lang.Object,您可能希望启用默认类型:查看ObjectMapper.enableDefaultTyping(...)更多信息。这实际上将允许包含(和使用)更大类别的类的类型信息,而无需添加注释。