Can Jackson determine the type of root object to deserialize when json includes the type property?

Suppose serialization in json includes the class name for the actual object using this annotation in the class:

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

So for example json:

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

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

 objectMapper.readValue(value, Object.class); 

which actually doesn't work, it returns the card.

+7
java json jackson
source share
4 answers

Well, of course, it is possible to do this, although I personally have never used Jackson in this way. You can deserialize it to a JsonNode object and then convert it to the appropriate type.

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

Output:

My class

+5
source share
  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.

+2
source share

What you want to use is Jackson's Political Exile .

+2
source share

Yes, but there is a caveat: the type you give MUST be something that includes @JsonTypeInfo that you specify. Object.class will not be unless you use โ€œmixing annotationsโ€ to link it.

However, if you need to add type information for the properties (of the declared type) of java.lang.Object , you probably want to enable the default setting: see ObjectMapper.enableDefaultTyping(...) for more information. This will actually allow you to include (and use) type information for larger class categories, without having to add annotations.

+1
source share

All Articles