Skip to content

OpenAPI 3.2 model support: SpecVersion.V32 platform + $self/Parameter/additionalOperations/MediaType fields - #5326

Draft
khayashi4337 wants to merge 16 commits into
swagger-api:masterfrom
khayashi4337:oas32-full-support
Draft

khayashi4337 wants to merge 16 commits into
swagger-api:masterfrom
khayashi4337:oas32-full-support

Conversation

@khayashi4337

Copy link
Copy Markdown

Status: Draft — blocked on #5253, #5254, #5255

This PR is not ready to merge. It is built directly on top of three other
open, unreviewed PRs from other contributors, none of which have landed yet:

I opened this as a draft so the remaining OAS 3.2 model work is visible and
reviewable in context, without implying it's ready to merge ahead of the PRs
it depends on. Once #5253/#5254/#5255 land (in whatever form the maintainers
prefer), I'll rebase this on top of the merged result and drop the
now-duplicate commits.

What this adds (on top of #5253/#5254/#5255)

Working toward full OpenAPI 3.2 model support (tracked in #2248):

  • SpecVersion.V32 and a 3.2 Jackson mapper/gating platform (Json32/
    Yaml32), following the existing 3.0/3.1 mixin pattern. Wires up
    PathItem.query (from feat: support the OpenAPI 3.2 QUERY method in PathItem and the JAX-RS reader #5253) so it's actually serialized for 3.2 documents
    instead of being unconditionally hidden.
  • OpenAPI.$self (root document canonical-URI field)
  • Parameter 3.2 additions: in: querystring (new QueryStringParameter
    type) and style: cookie
  • MediaType/Encoding nested encoding: prefixEncoding, itemEncoding
  • PathItem.additionalOperations (arbitrary-named operations beyond the 8
    fixed HTTP methods), following the minimal-addition option from a design
    memo evaluated separately (kept fixed fields, added a side map — avoids an
    API/serializer redesign that would diverge further from feat: support the OpenAPI 3.2 QUERY method in PathItem and the JAX-RS reader #5253's approach)
  • MediaType.$ref (Reference Object semantics) + Components.mediaTypes
  • Simpler fixed-field additions: Server.name, Tag.summary/parent/kind,
    ApiResponse.summary, Example.dataValue/serializedValue,
    SecurityScheme.deprecated/oauth2MetadataUrl, OAuth device-flow fields,
    XML.nodeType, Discriminator.defaultMapping

Known limitations (disclosed, not blocking this draft)

  • The openapi31 boolean's meaning is widened to "3.1-family or later" as a
    stopgap; once SpecVersion gains more structure upstream this should be
    revisited.
  • 3.2 output is currently only reachable by calling Json32/Yaml32
    directly — SwaggerConfiguration, the jaxrs2 SwaggerSerializers, and the
    Maven/Gradle plugins don't yet select the 3.2 mapper. Wiring that up is a
    separate, larger change.
  • A handful of generators/consumers that call PathItem.readOperationsMap()
    directly (bypassing higher-level traversal) will now also see QUERY as a
    legitimate enum value, which is a natural consequence of feat: support the OpenAPI 3.2 QUERY method in PathItem and the JAX-RS reader #5253 rather than
    something this PR introduces.

Testing

Full reactor mvn clean install: 21 modules, all green. swagger-core
module 842 tests, swagger-jaxrs2 module 232 tests, 0 failures. New coverage
added across OpenAPI3_2SerializationTest, ValidationAnnotationsUtilsTest,
and QueryMethodTest.


🤖 Generated with Claude Code

CommanderGeek and others added 16 commits July 24, 2026 17:42
Add the `query` HTTP method introduced in OpenAPI 3.2 to PathItem:
field, accessors and fluent builder, HttpMethod.QUERY enum constant,
and wiring in readOperations, readOperationsMap, operation(), equals,
hashCode and toString. Adds model tests plus a swagger-core
serialization round-trip.

Refs swagger-api/swagger-parser#2248 (swagger-api/swagger-parser#2248)
  Route the "query" method in Reader.setPathItemOperation onto
  PathItem.query(), and include query operationIds in
  extractOperationIdFromPathItem. Adds QueryMethodTest.
  No new public API: ReaderUtils.getHttpMethodFromCustomAnnotations
  already resolves any @HttpMethod-meta-annotated annotation, so an
  application's own @query binding maps with no further support. The
  @query here is a test fixture standing in for that binding
  Refs swagger-api/swagger-parser#2248 (swagger-api/swagger-parser#2248)
…athItem.query for 3.2

Builds on the SpecVersion-based mapper selection introduced by cherry-picked
upstream PRs swagger-api#5255 (ObjectMapperFactory refactor) and
swagger-api#5254 (test refactor), and on the PathItem.query model
from CommanderGeek's swagger-api#5253.

- SpecVersion.V32 added to io.swagger.v3.oas.models.SpecVersion
- ObjectMapperFactory: case V32 shares the 3.1 serializer modifier
  (Schema31Serializer/MediaTypeSerializer/ExampleSerializer), the 3.1 mixin
  set, and registers DeserializationModule32; PathItem gets PathItem32Mixin
  (query not ignored) while 3.0/3.1 keep PathItemMixin (@JsonIgnore query).
  All three specVersion switches now throw on unknown versions, matching
  SpecVersionMappers
- New Json32/Yaml32 utility classes and createJson32/createYaml32 factories
- Deserializer family: protected boolean openapi31 kept (deprecated) for
  subclass compatibility; version now flows through overridable specVersion()
  + mapper() (SpecVersionMappers resolves Json/Json31/Json32 singletons)
- New *32Deserializer variants (Paths/Callback/ApiResponses/Parameter/
  SecurityScheme/Model) + OpenAPI32Deserializer setting specVersion V32;
  DeserializationModule32 wires them
- ModelDeserializer: inner JsonSchema conversions now use mapper() so the
  ambient version propagates (previously hardcoded to the 3.1 mapper; needed
  for V32, no behavior change for 3.0/3.1 documents)
- Existing "3.1 or later" version predicates widened to cover V32, using the
  codebase's != V30 convention: OpenAPI.toString (webhooks/
  jsonSchemaDialect), Schema.toString (3.1 JSON Schema keywords),
  ValidationAnnotationsUtils.applyDecimal{Min,Max}Constraint

Tests: OpenAPI3_2SerializationTest (12 tests) verifies query round-trips in
3.2 JSON and YAML, stays hidden in 3.0/3.1, binds in nested PathItems
(webhooks/components.pathItems/callbacks), the V32 deserializer family binds
parameters/responses/schemas/securitySchemes, and toString prints
webhooks/jsonSchemaDialect for V32 but not V30.
Full reactor: mvn clean install, 21 modules, all tests pass.
Adds the fixed fields introduced by OpenAPI 3.2 to the model, serialized
and deserialized only under SpecVersion.V32:

- Server.name
- Tag.summary, Tag.parent, Tag.kind
- ApiResponse.summary
- Example.dataValue, Example.serializedValue (with dataValueSetFlag,
  mirroring valueSetFlag so an explicit null dataValue can be emitted)
- MediaType.itemSchema
- SecurityScheme.deprecated, SecurityScheme.oauth2MetadataUrl
- OAuthFlows.deviceAuthorization and OAuthFlow.deviceAuthorizationUrl
- XML.nodeType
- Discriminator.defaultMapping

A new @OpenAPI32 marker annotation documents the new accessors, matching
the existing @OpenAPI30/@OpenAPI31 convention. Fields deprecated by the
3.2 specification (Example.value, XML.attribute, XML.wrapped) are kept
without @deprecated since they remain valid for 3.0/3.1 documents;
mutual-exclusion rules are documented in javadoc only.

Version gating follows the existing mixin pattern: new *30Mixin classes
hide the 3.2 fields for the V30 and V31 mappers (registered for both
cases, as DateSchemaMixin already is), while V32 keeps the regular
mixin. Discriminator gains a dedicated Discriminator32Mixin since the
31 mixin is shared with V32 today. SecuritySchemeDeserializer parses
deprecated/oauth2MetadataUrl only when specVersion() == V32.
OpenAPI.$self declares the canonical URI of the root document (OpenAPI
3.2). Serialized/deserialized only under V32 via the new OpenAPI32Mixin;
OpenAPIMixin and OpenAPI31Mixin ignore it so 3.0/3.1 output and parsing
are unchanged.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add ParameterIn.QUERYSTRING annotation enum value and
Parameter.StyleEnum.COOKIE. New QueryStringParameter model binds
in: querystring under the V32 deserializer only; earlier versions
keep the existing unknown-in behavior (null). Semantic constraints
(content required, no schema/style/explode/allowReserved, uniqueness)
are documented on the model and left to parser-side validation,
consistent with the lenient model convention.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
MediaType gains prefixEncoding (list) and itemEncoding; Encoding gains
nested encoding map plus prefixEncoding and itemEncoding for recursion.
All gated to V32: MediaType30Mixin hides the new MediaType fields and a
new Encoding30Mixin hides the new Encoding fields for 3.0/3.1 output and
parsing (and the V30-style converter mapper). Mutual-exclusion rules
with 'encoding' are documented on the model; enforcement is parser-side.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
PathItem gains additionalOperations, a Map<String, Operation> for HTTP
methods beyond the fixed fields (minimal approach per the design memo:
fixed fields stay, no internal map rework). Keys keep original case for
round-trip; duplicate fixed-method keys are kept leniently with
enforcement left to parser-side validation. readOperations() now
includes the additional operations so existing traversal picks them up.
Hidden from 3.0/3.1 (and the converter mapper) via PathItemMixin.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
OpenAPI 3.2 allows content-related maps (Parameter/Header/RequestBody/
ApiResponse content) to hold Reference Objects, and adds a reusable
Components.mediaTypes map. MediaType gains a '$ref' property (minimum-change
approach: Content stays Map<String,MediaType>) and Components gains
'mediaTypes'.

V30/V31/converter mappers hide both via MediaType30Mixin, ComponentsMixin and
Components31Mixin; a new Components32Mixin exposes mediaTypes for 3.2.
SpecFilter now copies mediaTypes and collects schema refs inside mediaTypes
entries and itemSchema so unreferenced pruning keeps needed schemas.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- SpecFilter clones component schemas with the document's version
  (Json32 for 3.2) instead of always 3.0/3.1, and collects
  discriminator.defaultMapping references during unreferenced pruning
- MediaType $ref no longer masks sibling schema/itemSchema/encoding
  references during pruning, fixing a pre-3.2 regression
- style: cookie is rejected by pre-3.2 serializers like it already is
  by pre-3.2 deserializers
- jaxrs2 Reader routes custom HTTP methods to additionalOperations
  preserving declared case, matches fixed methods case-insensitively,
  and gates in: querystring on OpenAPI 3.2 through the whole annotation
  processing chain

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@Mattias-Sehlstedt

Copy link
Copy Markdown
Contributor

For the Tags changes I also have master...Mattias-Sehlstedt:swagger-core:support-oas-32-tags since before, which should basically be a full implementation (but not rebased). But I have not done a PR or similar for it since I am waiting on swagger-core to inform us of how they want to handle the openapi31 boolean and how to harmonize the OAS versioning in general (now different components handle it very differently).

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.

3 participants