-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Search before asking
- I searched in the issues and found nothing similar.
Describe the bug
When using Jackson with frameworks such as Immutables where users are expected to write bean definitions as abstract types and let the framework generate concrete implementations, Jackson annotations on the abstract type sometimes have no effect, or worse, trigger bugs. This appears to be due to the assumption in BeanDeserializerFactory.addBeanProps that creator properties do not need to be considered for abstract types. In particular, deserialisation fails with a bizarre exception in in the following situation:
- The type to be deserialised is abstract but with a defined
ValueInstantiator(e.g. from a@JsonCreatorannotated factory method). - The property to be deserialised has a getter but no setter.
- The type of the property to be deserialised is also abstract.
- The getter has a
@JsonTypeInfoannotation withinclude = JsonTypeInfo.As.EXTERNAL_PROPERTY.
Version Information
2.17.1
Reproduction
See attached: example.zip
Expected behavior
No response
Additional context
Deserialisation fails with the following exception:
Unexpected token (VALUE_STRING), expected START_ARRAY: need Array value to contain `As.WRAPPER_ARRAY` type information for class example.TypedData$Value
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 20] (through reference chain: example.TypedData["value"])
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_STRING), expected START_ARRAY: need Array value to contain `As.WRAPPER_ARRAY` type information for class example.TypedData$Value
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 20] (through reference chain: papaya.struct.jackson.TypedData["value"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1913)
at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1699)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:141)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:96)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromObject(AsArrayTypeDeserializer.java:61)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:263)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:570)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:440)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1493)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4905)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3848)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3816)
Notice that the call chain goes through BeanDeserializer.deserializeFromObjectUsingNonDefault rather than the expected BeanDeserializer.deserializeWithExternalTypeId. This is because _externalTypeIdHandler is null, which is because when BeanDeserializerBase.resolve is called, _beanProperties is empty (!), which is because BeanDeserializerFactory.addBeanProps ignores creator properties when the type is abstract. Changing the value of isConcrete in addBeanProps to true while running in a debugger suffices to fix this problem, though I cannot say if this has any other effects.