Skip to content

revert: auto-set nullable for Kotlin nullable types (#3256)#3276

Open
thejeff77 wants to merge 1 commit intospringdoc:mainfrom
thejeff77:revert/kotlin-nullable-property-customizer
Open

revert: auto-set nullable for Kotlin nullable types (#3256)#3276
thejeff77 wants to merge 1 commit intospringdoc:mainfrom
thejeff77:revert/kotlin-nullable-property-customizer

Conversation

@thejeff77
Copy link
Copy Markdown
Contributor

Summary

Reverts #3256. The KotlinNullablePropertyCustomizer auto-marks Kotlin T? as nullable with no per-property opt-out, which silently produces incorrect specs for backends using @JsonInclude(NON_NULL). This restores pre-#3256 behavior pending an upstream NullableMode proposal in swagger-core.

Why revert rather than patch

The customizer auto-marks any Kotlin T? property as nullable in the generated schema. This is correct only when Jackson actually serializes null values onto the wire — i.e., default Jackson configuration. For backends that use @JsonInclude(NON_NULL) (a widespread Jackson convention) the resulting spec is wrong: it claims null can appear when in fact Jackson strips null fields entirely.

The natural per-property override would be @Schema(nullable = false). This cannot be honored. @Schema.nullable() is a boolean defaulting to false, which means via reflection there is no way to distinguish "user explicitly wrote nullable = false" from "user never specified anything." This is a known design wart on @Schema's legacy boolean fields — the same issue swagger-core addressed for required by introducing RequiredMode in 2022 (swagger-api/swagger-core#4221, swagger-api/swagger-core#4286, commit b1729fcf1) and for readOnly/writeOnly by introducing AccessMode in 2018 (swagger-api/swagger-core#2675, swagger-api/swagger-core#2677). No equivalent NullableMode exists yet.

Without that override, this PR's auto-detection cannot be made correct for the population it impacts. A global enable/disable flag (proposed in #3269) addresses the symptom but not the underlying override gap — codebases that mix @JsonInclude(NON_NULL) and default-Jackson DTOs still have no clean answer, and shipping the flag adds global config surface for a problem that will be solved per-property upstream once NullableMode exists.

Path forward

  1. This revert — restores pre-feat: auto-set nullable: true for Kotlin nullable types in schema properties #3256 behavior. Users in the original Support for auto conversion of Kotlin nullable type to schema: { nullable: true } #906 cohort fall back to the explicit @field:Schema(nullable = true) annotation, the long-standing workaround they were using before feat: auto-set nullable: true for Kotlin nullable types in schema properties #3256.
  2. Swagger-core proposal for NullableMode { AUTO, NULLABLE, NOT_NULLABLE } mirroring RequiredMode. Issue/PR to be opened on swagger-api/swagger-core. This benefits both layers — the swagger-core @Nullable auto-detection added in 5001: Add support for @Nullable annotations in OpenAPI 3.1 schemas swagger-api/swagger-core#5018 (2025-11) hits the same override gap and would also use the new mode.
  3. Re-introduce KotlinNullablePropertyCustomizer once NullableMode ships upstream, with the customizer honoring NullableMode.NOT_NULLABLE as an explicit per-property override and NullableMode.AUTO (default) as the auto-detection trigger.

Background discussions

Test plan

Risk

Low. This is a literal git revert of the merge commit; no manual conflict resolution. Users relying on the auto-detection lose it and must re-add @field:Schema(nullable = true) until the upstream NullableMode work lands.

…nullable-schema-properties"

This reverts commit 6462e32, reversing
changes made to f634f54.
@thejeff77
Copy link
Copy Markdown
Contributor Author

Cross-link: the upstream NullableMode proposal referenced in the path-forward section is now open at swagger-api/swagger-core#5160.

@thejeff77
Copy link
Copy Markdown
Contributor Author

Note on CI: the failing `Java CI with Maven` check (`Non-resolvable parent POM for org.springdoc:springdoc-openapi-tests`) is pre-existing infrastructure, not caused by this revert. Same exact failure on:

  • the previous merge to `main` (run 24686358254, 2026-04-20)
  • run 24317160951 (2026-04-12, on the 3.0.3 line)
  • multiple intermediate `action_required` runs

This PR is a literal `git revert -m 1` of the #3256 merge commit — no manual conflict resolution, no test changes beyond the original PR's tests being deleted alongside the customizer they covered. The same code (pre-#3256) was passing CI before #3256 was introduced.

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.

1 participant