[JAVA, JAVA-SPRING, KOTLIN-CLIENT, KOTLIN-SPRING] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing

Merged
PI
19d ago
+13046-1122

Purpose

Complements the current oneOf Jackson polymorphism by making it possible to supply a default fallback value for deserialization. This is useful e.g. when you want to specify a default for deduction-based polymorphism (FasterXML/jackson-databind#3055), or when you want to fall back to some no-op class.

This feature is fully opt-in and has no effect on existing usage. Generated output is unchanged unless you explicitly set x-jackson-default-impl or typeInfoDefaultImpls.

What it adds

Emits @JsonTypeInfo(defaultImpl = ...) on polymorphic oneOf interfaces. Two opt-in ways to configure it (both default to disabled):

  • Vendor extension x-jackson-default-impl: <ClassName> on a schema.
  • Generator option typeInfoDefaultImpls: {SchemaName: ClassName}, which overrides the vendor extension when both are set for the same schema.

Class names are resolved via toModelName (honoring model mappings and DTO prefix/suffix); warns on overrides and unknown targets.

Scope

GeneratorSupport
java (client)deduction + discriminator
springdeduction + discriminator
kotlin-springdeduction + discriminator
kotlin (client)discriminator only
java-microprofiledisabled (template doesn't route through oneOf interface)

Resolution is centralized in AbstractJavaCodegen (shared by Java + Spring). Templates only emit defaultImpl when a value is resolved, so output is byte-for-byte identical to before for anyone who doesn't opt in.

Tests & docs

  • Tests added for Java client, Spring, kotlin-spring, and kotlin client, covering deduction/discriminator cases, config override, model-name suffix handling, and a noDefaultImplWhenNeitherSourceIsSet case that confirms no change when unconfigured.
  • New shared test spec 3_0/spring/jackson-default-impl.yaml.
  • Docs updated for java, spring, kotlin-spring, kotlin, and java-camel; new x-jackson-default-impl vendor extension registered.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request. - tagging kotlin, java, java-spring committee members: @bbdouglas, @sreeshas, @jfiala, @lukoyanov, @cbornet, @jeff9finger, @karismann, @Zomzog, @lwlee2608, @martin-mfg, @cachescrubber, @welshm, @MelleD, @atextor, @manedev79, @javisst, @borsch, @banlevente, @andrewemery, @4brunu, @yutaka0m, @stefankoppier, @e5l, @dennisameling

Summary by cubic

Adds an opt‑in Jackson default fallback for deserializing oneOf interfaces. Previously no default existed; now, when configured via x-jackson-default-impl or typeInfoDefaultImpls, generators emit @JsonTypeInfo(defaultImpl=...). Unconfigured outputs are unchanged.

  • Resolves defaults via shared JacksonDefaultImplResolver, preserving FQCNs (add import, emit simple name), honoring schema/import mappings and DTO prefix/suffix; typeInfoDefaultImpls overrides the vendor extension and warns on shadowed or unknown targets; logs use Locale.ROOT.
  • Emission:
    • java and spring: defaultImpl for deduction (Id.DEDUCTION) and discriminator (Id.NAME) oneOf interfaces.
    • kotlin-spring: deduction and discriminator; kotlin client: discriminator only.
    • java-microprofile: disabled; strips x-jackson-default-impl during model processing.
  • Template updates: keep @JsonTypeInfo for non‑discriminator oneOf when not using deduction; add defaultImpl to deduction annotations; avoid duplicate @JsonTypeInfo and render on its own line.
  • Build/docs/samples: move Gradle ext {} before the Android branch across Java templates; fix webclient useJspecify=true; document typeInfoDefaultImpls and the vendor extension; regenerate samples and CI workflows for Java RestClient, Spring Boot, kotlin-spring, kotlin client, and Java Camel; java-camel POJOs can render @JsonInclude/@JsonSetter(nulls=...) when configured.
  • Adds CodegenConstants.TYPE_INFO_DEFAULT_IMPLS; tests cover deduction/discriminator cases and config precedence across java, spring, kotlin-spring, and kotlin client.

Migration

  • To enable a default fallback, set x-jackson-default-impl: ClassName on a schema or configure typeInfoDefaultImpls: {SchemaName: ClassName}; the config option overrides the extension. No action required if you do not opt in.