Skip to content

fix: honour JSpecify @Nullable on controller parameters - #3378

Open
sharanggupta wants to merge 1 commit into
springdoc:mainfrom
sharanggupta:gh-3377-jspecify-nullable-request-param
Open

sharanggupta wants to merge 1 commit into
springdoc:mainfrom
sharanggupta:gh-3377-jspecify-nullable-request-param

Conversation

@sharanggupta

@sharanggupta sharanggupta commented Oct 6, 2026 •

Copy link
Copy Markdown

Summary

A JSpecify @Nullable (TYPE_USE only, the annotation Spring Framework 7 standardises on) declared on a controller method parameter is dropped before schema extraction. Spring already marks the parameter required: false, but its schema stays non-nullable, unlike the same parameter annotated with Spring's declaration-targeted @Nullable (app102). #3300 fixed this for flattened @ParameterObject fields; this applies the same treatment to direct parameters.

Change Plan

  • GenericParameterService.resolveTypeAndTypeAnnotationsForParameter: forward the annotations on the parameter's own AnnotatedType as well as those on its type arguments, by reusing annotationsFromAnnotatedType (made null-safe for parameters whose AnnotatedType cannot be resolved).
  • New webmvc regression app app274 (OAS 3.0 and 3.1) with @RequestParam @Nullable String / Integer using org.jspecify.annotations.Nullable; expected ["string","null"] / nullable: true. The same app has a @PathVariable @Nullable String id endpoint whose golden file shows the path parameter stays required: true and non-nullable, because SpringDocUtils.fixNullablePathParameter (nullable: true dropped for @Nullable @PathVariable parameters when using springdoc.api-docs.version=openapi-3-0 (regression in 3.1.1) #3358) still applies after this change.
  • CHANGELOG entry under Unreleased.

Annotations that target both PARAMETER and TYPE_USE (for example @Size) now appear in the merged annotation array for direct parameters the same way they already do for @ParameterObject fields since #3300; the existing suites (including app270's List<@Pattern String>) are unchanged.

Test Plan

SpringDocApp274Test fails on main (schema.type Expected: a JSON array got: string / Expected: nullable but none found) and passes with the fix. springdoc-openapi-starter-common (55 tests) and springdoc-openapi-starter-webmvc-api (655 tests) suites are green.

Fixes #3377

For a controller method parameter, GenericParameterService only forwarded
the annotations declared on the parameter's type arguments to swagger-core,
never the ones declared on the parameter type itself. A type-use-only
annotation such as the JSpecify @nullable (the annotation Spring Framework 7
standardises on) was therefore dropped before schema extraction: Spring
already marked the parameter as not required, but its schema stayed
non-nullable, unlike the same parameter annotated with Spring's declaration
targeted @nullable.

Flattened @ParameterObject fields were given both sets of annotations in
springdoc#3300. Apply the same treatment to direct parameters by reusing
annotationsFromAnnotatedType, made null-safe for the parameters whose
AnnotatedType cannot be resolved.

The regression app also covers a @PathVariable carrying the same
annotation, which the springdoc#3358 guard keeps non-nullable.

Fixes springdoc#3377
@sharanggupta
sharanggupta force-pushed the gh-3377-jspecify-nullable-request-param branch from 2ee61c2 to ada02a0 Compare October 6, 2026 20:58

This branch has not been deployed

No deployments
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.

JSpecify @Nullable on a controller method parameter is not reflected as nullable in the parameter schema

1 participant