Skip to content

NPE when serializing a LocalDate or LocalDateTime using AsDeductionTypeSerializer #296

@mike-reynolds-savient

Description

@mike-reynolds-savient

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

In v2.14.2 AsDeductionTypeSerializer was introduced.
Prior to this we could define an immutable interface as follows:

    @Nullable
    @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
    /* Complex/ nested classes should be added to this list for Jackson to check */
    @JsonSubTypes({
            @JsonSubTypes.Type(StoreField.class),
            @JsonSubTypes.Type(StringArray.class),
            @JsonSubTypes.Type(NumberArray.class),
            @JsonSubTypes.Type(QueryRequest.class) })
    T getValue();

and set a value of LocalDate, LocalDateTime, OffsetDateTime etc as the return of getValue()

This would serialize correctly with JsonMapper.builder().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) set.

We now get a "Cannot read field 'valueShape'" exception because AsDeductionTypeSerializer returns null if the WritableTypeId.valueShape is not a structure start token.
This results in an NPE within the LocalDateTimeSerializer class on line 89;

 if (typeIdDef.valueShape == JsonToken.START_ARRAY) {

Version Information

2.14.2

Reproduction

@Value.Immutable
@JsonSerialize(as = ImmutableQueryPredicate.class)
@JsonDeserialize(as = ImmutableQueryPredicate.class)
public interface QueryPredicate<T> extends Serializable {

    @Nullable
    @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
    /* Complex/ nested classes should be added to this list for Jackson to check */
    @JsonSubTypes({
            @JsonSubTypes.Type(StoreField.class),
            @JsonSubTypes.Type(StringArray.class),
            @JsonSubTypes.Type(NumberArray.class),
            @JsonSubTypes.Type(QueryRequest.class) })
    T getValue();

}
    @Test
    void testSerialiseLocalDatePredicate() {

        final QueryPredicate<LocalDateTime> dateTimePredicate = ImmutableQueryPredicate.<LocalDateTime>builder()
                .value(LocalDateTime.of(2022, 06, 24, 10, 23, 51))
                .build();

        final String asString = mapper.writeValueAsString(dateTimePredicate);
}

Expected behavior

If deduction cannot find the class it should return default property behaviour.

Additional context

FasterXML/jackson-databind#3711 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions