Existing property polymorphic deserialization does not work on enums
See original GitHub issueSeems like, enum-related deserialization annotations doesn’t work on polymorphic types with builders. Using the following main:
ObjectMapper om = new ObjectMapper();
String json = "{\"type\":\"ggwp\",\"name\":\"Hello\"}";
Endpoint endpoint = om.readValue( json, Endpoint.class );
System.out.println(endpoint);
This fails to deserialize due to the non-null requirement of Endpoint#type()
.
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of io.toro.integrate.labs.esb1271.AutoValue_EndpointImpl$Builder, problem: Missing required properties: type
at [Source: {"type":"ggwp","name":"Hello"}; line: 1, column: 30]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277)
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1441)
at com.fasterxml.jackson.databind.DeserializationContext.handleInstantiationProblem(DeserializationContext.java:1055)
...
I tried to set breakpoints to:
@JsonCreator Endpoint.Type#fromKey
- would’ve expected this to be used, so that proper fallback is taken care of@JsonValue Endpoint.Type#getKey
@JsonCreator EndpointImpl.Builder#create
- would’ve expected this to be used, so that the type be initialized
…and none of these methods are called. My goal was to deserialize all unknown endpoints into an EndpointImpl
, with type = Type.UNRECOGNIZED
. I even tried to implement custom JsonSerializer
and JsonDeserializer
for the enum, but both aren’t called either. I’m using jackson 2.8.6, with google’s auto value.
Edit: Actually, even if I specify an existing ‘type’ in the json, it’s not deserialized properly too.
Here’s the base class:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type",
defaultImpl = EndpointImpl.class )
@JsonSubTypes( value = {} ) // more subtypes
public abstract class Endpoint {
@JsonProperty( "name" ) public abstract String name();
@JsonProperty( "type" ) public abstract Type type();
public abstract static class Builder<B extends Builder<B>> {
@JsonProperty( "name" ) public abstract B name( String name );
@JsonProperty( "type" ) public abstract B type( Type type );
public abstract Endpoint build();
}
public static enum Type {
UNRECOGNIZED( "unrecognized" );
...
@JsonCreator
public static Type fromKey( String key ) {
for ( Type type : values() ) {
if ( type.key.equals( key ) )
return type;
}
return UNRECOGNIZED;
}
@JsonValue
public String getKey() {
return key;
}
}
}
This is extended by:
@AutoValue
@JsonDeserialize( builder = AutoValue_EndpointImpl.Builder.class )
public abstract class EndpointImpl extends Endpoint {
public static Builder builder() {
return new AutoValue_EndpointImpl.Builder()
.type( Type.UNRECOGNIZED );
}
@AutoValue.Builder
public abstract static class Builder extends Endpoint.Builder<Builder> {
@JsonCreator
private static Builder create() {
return EndpointImpl.builder();
}
public abstract EndpointImpl build();
}
}
Issue Analytics
- State:
- Created 6 years ago
- Comments:9 (7 by maintainers)
Top Results From Across the Web
Jackson Polymorphic Deserialization based on Enum
I'm working with JacksonPolymorphicDeserialization, this is my code which deserializes into the proper class based in the 'type' property:
Read more >Polymorphic deserialization with Jackson and no annotations
Problem. If we go directly invoking the /players endpoint, we'll face the InvalidDefinitionException as Jackson can't define to which class ...
Read more >Migrate from Newtonsoft.Json to System.Text.Json - .NET
Json has several ways to conditionally ignore a property on serialization or deserialization: DefaultContractResolver lets you select properties ...
Read more >How To Serialize and Deserialize Enums with Jackson
In this quick tutorial, we'll learn how to control the way Java Enums are serialized and deserialized with Jackson 2.
Read more >Enum DeserializationFeature - Adobe Developer
Feature that determines whether encountering of unknown properties (ones that do not map to a property, and there is no "any setter" or...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Ah. One problem with code as shown:
@JsonTypeInfo
must specify propertyvisible
:for type id to be exposed to regular
BeanDeserializer
, which can then map it to existing property. Without this, type id is considered metadata, consumed directly by databind itself. This is the default setting.The reason why visibility is not directly determine from
EXISTING_PROPERTY
(which would seem like a reasonable inference) is that there are couple of different uses for existing-property option: one being it would only be accessed via getter (or field) for serialization; but not necessarily set during deserialization.So, this needs to be added. With this setting, both String and enum-valued type id property does get property set, in a more simplified test I’ll add.
It does however look that this is not enough for your test case, so I will try digging deeper; it is possible that use of Creator properties could be the problem here, or that it is due to use as
defaultImpl
.At this point, I am not sure quite how to reproduce the issue and handling may have changed significantly over past 3 years. Closing now, may be re-filed with a simplified reproduction.