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

Đang mở
#3,395 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 14 ngày

@Shubchynskyi đang làm issue này rồi.

Từ ngày 29/10/2026.

  • #3396 của @Shubchynskyi — đang mở

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
45/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
java, spring-boot
Lĩnh vực
backend

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
Java
Star
3.7k
Fork
605
Merge trung bình
12 ngày 22 giờ
Pull request đã merge (30 ngày)
10

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của springdoc/springdoc-openapi

Tất cả issue của springdoc/springdoc-openapi

Issue tương tự

Thêm issue về Java

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.