#3314 fix has no effect if swagger-core resolved a schema before `ObjectMapperProvider` was created

Geschlossen
#3,395 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@Shubchynskyi arbeitet bereits daran.

Seit 29.10.2026.

  • #3396 von @Shubchynskyi — offen

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
45/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
java, spring-boot
Bereich
backend

Rechercherichtung

Start in ObjectMapperProvider, where the constructor registers SchemaTypeMixin on the shared Json31.mapper(), then follow SpringDocUtils.cloneViaJson and the fallback in AbstractRequestService.applyBeanValidatorAnnotations. Reproduce by creating a bean that calls AnnotationsUtils.resolveSchemaFromType before springdoc auto-configuration, then requesting /v3/api-docs for a constrained parameter. Done when cloning a JsonSchema with types no longer depends on mapper initialization order; run the relevant springdoc tests for OpenAPI 3.1 schema cloning.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Describe the bug

With OpenAPI 3.1, Json Processing Exception occurred: Cannot construct instance of java.util.HashSet … from String value ('string') (through reference chain: io.swagger.v3.oas.models.media.JsonSchema["type"]) is still logged for every parameter with a validation constraint (@Min, @Pattern, @Size, …), although #3314 should have fixed this in 3.1.1. As a consequence, AbstractRequestService.applyBeanValidatorAnnotations falls back to modifying the original, possibly shared schema, which is the case #3270 meant to avoid.

Cause

ObjectMapperProvider registers SchemaTypeMixin on the JVM-wide Json31.mapper() in its constructor. Jackson only applies mixins to deserializers built afterwards, and caches those deserializers.

swagger-core uses the same mapper: ModelResolver copies property schemas via AnnotationsUtils.clone, which reads them back through ModelDeserializer, which in turn calls Json31.mapper().convertValue(node, JsonSchema.class) after removing type from the node. If that happens before ObjectMapperProvider is created, the cached JsonSchema deserializer lacks the TypeSetDeserializer. Every later SpringDocUtils.cloneViaJson fails, because it does not remove type first.

This happens in any application whose own configuration resolves a schema while it is being created. User configuration beans are instantiated before springdoc's auto-configuration. In our case it was an OperationCustomizer bean:

@Bean
public OperationCustomizer errorResponseSchemas(SpringDocConfigProperties properties) {
	Schema schema = AnnotationsUtils.resolveSchemaFromType(ApiResponseBody.class, null, null, properties.isOpenapi31());
	// …
}

To Reproduce

  • Spring Boot: 4.1.1
  • springdoc-openapi: 3.1.1 and 3.2.0
  • swagger-core: 2.2.55
  • springdoc.api-docs.version=OPENAPI_3_1 (the default)
  1. A bean in the application's own configuration that calls AnnotationsUtils.resolveSchemaFromType(SomeDto.class, null, null, true) for a class with properties.
  2. A controller method with a constrained parameter, e.g. @RequestParam @Min(1) Integer pageSize.
  3. Request /v3/api-docs: the warning is logged for that parameter.

At that point, objectMapperProvider.jsonMapper() is Json31.mapper() and findMixInClassFor(Schema.class) returns SchemaTypeMixin, yet SpringDocUtils.cloneViaJson of a JsonSchema with types = [integer] falls back to returning the original object. The same clone succeeds in a fresh JVM without the early bean.

Expected behavior

The schema is copied regardless of what used Json31.mapper() before springdoc was initialized.

Workaround

Inject ObjectMapperProvider into the bean that resolves schemas early, so that springdoc configures the mapper first. This makes the warnings disappear in our application.

Possible fix

Don't change the shared Json31.mapper(). Let ObjectMapperProvider configure its own instance instead, e.g. ObjectMapperFactory.createJson31() with SchemaTypeMixin, as createJson already does for the standalone mappers. Alternatively, swagger-core could make the 3.1 type property readable back in the form it writes it (swagger-api/swagger-core#5264), which would make the mixin unnecessary.

Vorherrschende Sprache
Java
Sterne
3.7k
Forks
605
Ø Merge
4 T. 18 Std.
Gemergte PRs (30 T.)
21

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus springdoc/springdoc-openapi

Alle Issues in springdoc/springdoc-openapi

Ähnliche Issues

Weitere Issues zu Java

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.