Skip to content

OpenAPI 3.1 normalizer (#1)#163

Merged
keysersoft merged 1 commit into
mainfrom
keysersoft/openapi-3.1-normalizer
May 11, 2026
Merged

OpenAPI 3.1 normalizer (#1)#163
keysersoft merged 1 commit into
mainfrom
keysersoft/openapi-3.1-normalizer

Conversation

@keysersoft
Copy link
Copy Markdown
Contributor

Problem

FastAPI ≥ 0.100, recent NestJS, spring-doc 3.x and Hono all emit OpenAPI 3.1 natively. Our pipeline depends on swagger-parser 10.x which hard-rejects any `openapi` value other than 3.0.0–3.0.3 — including from `dereference()`. Customers were getting `Unsupported OpenAPI version: 3.1.0` and had to patch their bridges to emit 3.0 by hand (PR #5 in the customer's repo did this).

Fix

A small normalizer that rewrites the 3.1-only constructs we care about into their 3.0 equivalents in place, before swagger-parser sees the document, and relabels `openapi` to `3.0.3` so the parser proceeds.

Rewrites covered:

3.1 input 3.0 output
`type: [X, "null"]` `type: X` + `nullable: true`
`anyOf: [X, {type:"null"}]` unwrap `X` + `nullable: true`
`oneOf: [X, {type:"null"}]` same
`const: "x"` `enum: ["x"]`
`examples: [...]` (array) `example: examples[0]`
`exclusiveMinimum: ` `minimum: ` + `exclusiveMinimum: true`
`exclusiveMaximum: ` `maximum: ` + `exclusiveMaximum: true`

The `components.examples` map (object, not array) is preserved.

Also forwards `nullable` and `example` through `paramToJsonSchema` / `flattenSchema` so the normalized fields actually survive into the generated tool schemas. Without this, the normalizer's work was being silently dropped when the parser flattened parameters.

Out of scope

  • Webhooks, jsonSchemaDialect, info.summary — survive untouched, not used by tool extraction.
  • Full replacement of swagger-parser (the "stradone giusto" with `@redocly/openapi-core`) — left for a future PR.

Test plan

  • 16 unit tests for the normalizer (`openapi-3.1-normalizer.spec.ts`).
  • 3 E2E tests in `openapi.parser.spec.ts` covering a FastAPI-style 3.1 spec end-to-end.
  • Full backend test suite: 620 passed, 0 regressions.

FastAPI, recent NestJS, spring-doc 3.x and Hono emit OpenAPI 3.1
natively. Our pipeline depends on swagger-parser 10.x which
hard-rejects any openapi version other than 3.0.0–3.0.3 — including
from dereference(). Customers got 'Unsupported OpenAPI version' and
had to patch their bridge to emit 3.0 by hand.

Fix: a small normalizer that rewrites the 3.1-only constructs we care
about into 3.0 equivalents in place, *before* swagger-parser sees the
document, and relabels openapi to 3.0.3 so the parser proceeds:

  type:[X,'null']        -> type:X + nullable:true
  anyOf+null branch      -> unwrap remaining branch + nullable:true
  oneOf+null branch      -> same
  const:'x'              -> enum:['x']
  examples:[...] (array) -> example:examples[0]
  exclusiveMinimum:<n>   -> minimum:<n> + exclusiveMinimum:true
  exclusiveMaximum:<n>   -> maximum:<n> + exclusiveMaximum:true

The components.examples map (object form) is left alone.

Also forward 'nullable' and 'example' through paramToJsonSchema and
flattenSchema so the normalized fields survive into the generated
tool schemas (without this, the normalizer's work was lost when the
parser flattened parameters).
Comment thread packages/backend/src/connectors/parsers/openapi-3.1-normalizer.ts Dismissed
@keysersoft keysersoft merged commit 580bc58 into main May 11, 2026
10 of 11 checks passed
@keysersoft keysersoft deleted the keysersoft/openapi-3.1-normalizer branch May 11, 2026 15:27
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.

2 participants