How can I conditionally make type information visible to Jackson deserialization?

Viewed 41

I am writing some code that deals with various message Body types, which may be extended by plugins. Because some of the infrastructure might not know about specific types, I want to have a catch-all generic fallback class that can hold a deserialized "anything". I tried this:

@JsonTypeInfo(use = NAME, visible = true, defaultImpl = UnknownBody)
abstract class Body {
    @NotNull
    String text
}

class UnknownBody extends Body {
    @JsonProperty('@type')
    String _bodyType

    @JsonAnyGetter
    @JsonAnySetter
    Map<String, Object> _properties = new HashMap<>()
}

This works, but when I try to deserialize a known Body subtype, I get an exception saying that the @type property is not found on them. So I tried splitting the @JsonTypeInfo directive:

@JsonTypeInfo(use = NAME, defaultImpl = UnknownBody)
abstract class Body {
    @NotNull
    String text
}

@JsonTypeInfo(use = NAME, visible = true)
class UnknownBody extends Body {
    @JsonProperty('@type')
    String _bodyType

    @JsonAnyGetter
    @JsonAnySetter
    Map<String, Object> _properties = new HashMap<>()
}

This results in a null value for _bodyType; apparently the type info is removed from the deserializer early in the process.

Is there a clean way to explain to Jackson that I want the type discriminator to be set on the UnknownBody class without causing it to blow up on other subclasses, and without using ignoreUnknown, which could cause silent mishandling in other subtypes?

0 Answers
Related