jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

Feature request: AS_EMPTY as DeserializationFeature

Open jlous opened this issue 3 years ago • 6 comments

I wish I could configure my object mapper to use "Nulls.AS_EMPTY" as default for deserializing list fields.

  • When I design with non-nullable lists, I commonly do so as a general design principle for the entire model, not just particular fields
  • It is sometimes desirable to use the same Pojos for multipe integrations with different requirements. It is therefore good to be able to configure (de)serialisation on a per-integration object mapper level rather than globally on the model.
  • I generally like to keep my domain classes as "clean" as possible

The perfect solution for me would automatically adjust to whether my kotlin field was nullable or not, but a fixed policy will do the job for most cases.

jlous avatar Oct 25 '22 08:10 jlous

Is this Kotlin specific? If so, could you move this the jackson-module-kotlin issues list?

pjfanning avatar Oct 25 '22 12:10 pjfanning

Not really. Only the extra wish at the end. Actually, I see now that jackson-module-kotlin already has KotlinFeature.NullToEmptyCollection, whihc will solve my curetn use-case.

But a similar feature would still be highly relevant in Java, and I believe DeserializationFeature would be the right place for it.

jlous avatar Oct 25 '22 14:10 jlous

Ok yes, I think this is the right place for the issue.

This would not belong under DeserializationFeature since that is meant for more cross-cutting concerns (ideally not datatype-specific features, although there are a few legacy settings from time before we had other options).

But I think this should work as "config override" per type, although would have to be considered at general List.class level. And would not just be for Lists or just "as Empty" so would have wider potential usability.

It is already possible to define such defaults; for all types you'd use something like:

ObjectMapper mapper = JsonMapper.builder()
    .defaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY))
     .build();

but variant for target type of List.class may or may not work; would be worth testing (and if not, supporting).

cowtowncoder avatar Oct 25 '22 21:10 cowtowncoder

It is already possible to define such defaults; for all types you'd use something like:

ObjectMapper mapper = JsonMapper.builder()
    .defaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY))
     .build();

but variant for target type of List.class may or may not work; would be worth testing (and if not, supporting).

I think applying Nulls.AS_EMPTY for collection only is too broad of a scope.

Can we consider creating collection-specific feature? something like CollectionFeature. READ_NULL_TO_EMPTY? Like we have for EnumFeature?

JooHyukKim avatar Feb 13 '23 13:02 JooHyukKim

Like we have for EnumFeature?

Unfortunately no, as I don't like having features that overlap with other configuration functionality, and ConfigOverride is the main mechanism (along with @JsonSetter annotation) for applying alternate Null handling. It exists, is used; and if we had different way of configuring, we would have to figure out how to merge different "dimensions" of configurability.

ConfigOverride has the challenge of how to apply scopes as target type must be indicated with Class. I will note that one can apply definition for List, alternatively; question then is just whether it's possible to support multiple levels (that is, if no definition for List, then check for Collection -- this is not used by any of existing deserializers).

cowtowncoder avatar Feb 13 '23 22:02 cowtowncoder

@jlous I added a test case to validate the feature you suggested in this issue in #3783 . Could you check if it's what you were thinking?

JooHyukKim avatar Feb 15 '23 15:02 JooHyukKim