Skip to content

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

Merged
wing328 merged 29 commits into
OpenAPITools:masterfrom
Picazsoo:feature/use-deduction-default
Sep 20, 2026
Merged

wing328 merged 29 commits into
OpenAPITools:masterfrom
Picazsoo:feature/use-deduction-default

Conversation

@Picazsoo

@Picazsoo Picazsoo commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

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

Generator Support
java (client) deduction + discriminator
spring deduction + discriminator
kotlin-spring deduction + discriminator
kotlin (client) discriminator only
java-microprofile disabled (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


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.

Written for commit a007a4c. Summary will update on new commits.

Review in cubic

…foDefaultImpls support

   Emit `@JsonTypeInfo(defaultImpl = ...)` for both deduction-based and
   discriminator-based oneOf interfaces.

   Two configuration sources (config option takes precedence):
   - Schema extension: `x-jackson-default-impl: ClassName`
   - Config option: `typeInfoDefaultImpls: {SchemaName: ClassName}`

   The resolved class name passes through `toModelName()` so schemaMapping,
   importMapping, and DTO prefix/suffix are all honoured. A LOGGER.warn is
   emitted when the config option shadows a schema-level annotation.
@Picazsoo
Picazsoo marked this pull request as ready for review June 5, 2026 13:29
@Picazsoo
Picazsoo marked this pull request as draft June 5, 2026 13:29

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

public static final String USE_SEALED_RESPONSE_INTERFACES = "useSealedResponseInterfaces";
public static final String COMPANION_OBJECT = "companionObject";
public static final String SUSPEND_FUNCTIONS = "suspendFunctions";
public static final String TYPE_INFO_DEFAULT_IMPLS = "typeInfoDefaultImpls";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to CodegenConstants ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Picazsoo Could you also add the feature to the java generators?
See src/main/resources/Java/deductionAnnotation.mustache and the different typeInfoAnnotation.mustache under java/libraries

@Picazsoo Picazsoo Jun 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will take a look at it. And this is early implementation without any polish. I marked temporarily as "ready for review" just to gather early feedback from Cubic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But thanks for the review! I will properly tag you once I think it is ready for wasting human review time (-:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jpfinne, I added it to the java generators as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now ready for review

Picazsoo and others added 4 commits June 17, 2026 23:18
# Conflicts:
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java
…Java generators

- Add TYPE_INFO_DEFAULT_IMPLS/DESC constants to CodegenConstants (addresses
  reviewer request to avoid duplication across SpringCodegen and
  KotlinSpringServerCodegen)
- Move typeInfoDefaultImpls field, option registration, processOpts parsing,
  and x-jackson-resolved-default-impl resolution loop from SpringCodegen into
  AbstractJavaCodegen so all Java generators inherit the feature
- Remove duplicated code from SpringCodegen; update KotlinSpringServerCodegen
  to reference CodegenConstants.TYPE_INFO_DEFAULT_IMPLS and apply the same
  safe instanceof cast fix already present in SpringCodegen
- Update Java/deductionAnnotation.mustache: emit defaultImpl = X.class on
  @JsonTypeInfo(use = DEDUCTION) when x-jackson-resolved-default-impl is set
- Update Java/typeInfoAnnotation.mustache: emit defaultImpl = X.class on both
  @JsonTypeInfo(use = NAME) variants (discriminator present/absent) via
  discriminator.vendorExtensions.x-jackson-resolved-default-impl
- Add JavaClientCodegenTest tests covering deduction, discriminator,
  typeInfoDefaultImpls config option, and absence cases for Java client

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Picazsoo Picazsoo changed the title feat(kotlin-spring, java-spring): add x-jackson-default-impl / typeInfoDefaultImpls support [kotlin-spring, java(-spring)] -feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing Jun 17, 2026
@Picazsoo Picazsoo changed the title [kotlin-spring, java(-spring)] -feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing [KOTLIN-SPRING, JAVA(-SPRING)] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing Jun 17, 2026
@Picazsoo
Picazsoo marked this pull request as ready for review June 17, 2026 22:07

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 17 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@Picazsoo Picazsoo changed the title [KOTLIN-SPRING, JAVA(-SPRING)] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing [JAVA, JAVA-SPRING, KOTLIN-SPRING] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing Jun 18, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 issues found across 27 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/kotlin-spring/typeInfoAnnotation.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/kotlin-spring/typeInfoAnnotation.mustache:6">
P1: Missing validation that the resolved defaultImpl is a subtype of the polymorphic base; misconfigured `x-jackson-default-impl` or `typeInfoDefaultImpls` values will compile but fail at runtime during deserialization.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread docs/generators/java-play-framework.md Outdated
Comment thread docs/generators/java-micronaut-server.md Outdated
Comment thread docs/generators/jaxrs-spec.md Outdated
Comment thread docs/generators/java-undertow-server.md Outdated
Comment thread docs/generators/java-dubbo.md Outdated
Comment thread docs/generators/java-inflector.md
Comment thread docs/generators/java-wiremock.md Outdated
Comment thread docs/generators/java-microprofile.md Outdated
Comment thread docs/generators/java-play-framework.md Outdated
@Picazsoo Picazsoo changed the title [JAVA, JAVA-SPRING, KOTLIN-SPRING] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing [JAVA, JAVA-SPRING, KOTLIN-CLIENT, KOTLIN-SPRING] - feature - add x-jackson-default-impl / typeInfoDefaultImpls support to allow specifying of fallback schema when deserializing Jun 18, 2026
# Conflicts:
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java
@Picazsoo
Picazsoo requested a review from jpfinne July 1, 2026 12:48
@Picazsoo

Picazsoo commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Tagging @wing328 - please consider if this contribution makes sense and if it would make sense for 7.24.0

Picazsoo added 2 commits July 13, 2026 00:12
# Conflicts:
#	docs/generators/kotlin-spring.md
#	docs/generators/kotlin.md
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 333 files

Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.

Re-trigger cubic

Comment thread docs/generators/kotlin.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 74 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@Picazsoo

Picazsoo commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Hi @wing328 , I wonder if this feature is acceptable or not as is?

Picazsoo and others added 2 commits August 13, 2026 20:21
…on-default

# Conflicts:
#	docs/generators/java-camel.md
#	docs/generators/spring.md
#	modules/openapi-generator/src/main/java/org/openapitools/codegen/VendorExtension.java
#	modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 30 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 329 files

Requires human review: Auto-approval blocked by 2 unresolved issues from a previous review of this commit.

Re-trigger cubic

Comment thread docs/generators/kotlin.md Outdated
- Extract shared JacksonDefaultImplResolver used by AbstractJavaCodegen,
  KotlinClientCodegen and KotlinSpringServerCodegen (dedup resolution logic)
- Preserve external/FQN class names for defaultImpl (add import, emit simple
  name) instead of mangling them through toModelName
- JavaMicroprofileServerCodegen: strip x-jackson-default-impl before model
  post-processing so the vendor extension no longer leaks defaultImpl
- Guard typeInfoAnnotation with discriminator in Java/oneof_interface.mustache
  so deduction-based oneOf keeps defaultImpl and drops the bogus property=""
- Correct kotlin-client typeInfoDefaultImpls description (discriminator/jackson
  only) and regenerate docs/generators/kotlin.md
- Move ext{} version block before the android branch in Java build.gradle
  templates (base + 12 libraries) to fix -Ptarget=android config failure
- Default stricter generateJsonInclude/JsonSetterNulls options on Spring-family
  jackson-default-impl configs and render them in java-camel-server pojo
- Add useDeductionForOneOfInterfaces to the restclient sample config
- Regenerate all affected samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 134 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Picazsoo and others added 6 commits August 19, 2026 20:35
…ering

- oneof_interface.mustache: render typeInfoAnnotation for non-discriminator
  oneOf when not using deduction, so sealed oneOf interfaces keep their
  @JsonTypeInfo/@JsonIgnoreProperties (byte-for-byte stable with master);
  only suppress it in the deduction path to avoid a duplicate @JsonTypeInfo
- deductionAnnotation.mustache: add a leading newline and render at column 0
  (mirroring typeInfoAnnotation) so @JsonTypeInfo no longer lands on the same
  line as @generated
- webclient build.gradle.mustache: move the stray jspecify implementation out
  of the ext{} block into dependencies{} so it runs after the java plugin
  creates the implementation configuration (fixes useJspecify=true builds
  while keeping ext{} before the android branch)
- Regenerate affected Java client samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on-default

# Conflicts:
#	modules/openapi-generator/src/main/resources/Java/libraries/apache-httpclient/build.gradle.mustache
#	samples/client/echo_api/java/apache-httpclient/build.gradle
#	samples/client/petstore/java/apache-httpclient-jackson3/build.gradle
#	samples/client/petstore/java/apache-httpclient/build.gradle
The forbiddenapis check rejects locale-dependent String.format(String, Object...).
Pass Locale.ROOT explicitly, matching the convention used across the codegen
language classes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Picazsoo

Copy link
Copy Markdown
Contributor Author

Hello @wing328, I made the PR up-to-date and resolved all the standing issues.

@wing328
wing328 merged commit cc2e80d into OpenAPITools:master Sep 20, 2026
324 checks passed
@wing328

wing328 commented Sep 20, 2026

Copy link
Copy Markdown
Member

Just merged it. Sorry for the delay as I missed it.

@Picazsoo

Copy link
Copy Markdown
Contributor Author

No problem, thanks a bunch!

@wing328 wing328 added this to the 7.26.0 milestone Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants