Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@type'

user2221654 picture user2221654 · Apr 25, 2017 · Viewed 12.8k times · Source

I am getting below exception during deserialization , the guest profile is a nested object within the Root object (few levels within it). i dont have control over how it is serialized since I am only the consumer of this message from a kafka topic. Is there a way to make this work, other than setting

mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE,false);

which works for me and returns null for GuestProfile with other attributes being populated. But, I need a way to customize the deserialization for this particular nested object in the JSON and have it populate.

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@type' that is to contain type id (for class com.test.GuestProfile)

Answer

Gonfi den Tschal picture Gonfi den Tschal · Aug 28, 2017

The Jackson JSON library throws this exception when interfaces or polymorphic types are used. GuestProfile must be a polymorphic type, either an interface, an abstract class, or it is the actual implementation and it has a parent.

This polymorphic type may be configured to use the type hint in JSON. Look for something like

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)

on the Java type.

You can change the default @type name, for example to just "type":

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")

The serialized JSON value of your object currently needs that additional attribute '@type'. Since you cannot change the generation of the JSON, this is not a solution for you.

If there's only a single implementation, then you can use:

@JsonDeserialize(as = GuestProfile.class)

It's a rather new feature of Jackson, it hasn't always been there.

Otherwise, you can customize the deserialization process. You can configure your own deserializer, and then look into the incoming value, and decide based on the content to which target object type you deserialize.

See https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization