Skip to content

feat(json-schema-document): render standalone JSON Schema 2020-12 - #11117

Draft
robert-hebel-sb wants to merge 5 commits into
mainfrom
feat/json-schema-2020-12-detection
Draft

robert-hebel-sb wants to merge 5 commits into
mainfrom
feat/json-schema-2020-12-detection

Conversation

@robert-hebel-sb

@robert-hebel-sb robert-hebel-sb commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Description

Swagger UI renders standalone JSON Schema 2020-12 documents in SwaggerUI({ url }). A document is one when its root $schema is https://json-schema.org/draft/2020-12/schema (an empty fragment # is normalised) and its root has none of openapi, swagger, asyncapi, arazzo. A root $schema naming any other dialect (a custom meta-schema, an OpenAPI dialect, http://json-schema.org/draft/2020-12/schema, a draft not supported yet) is refused with "Unable to render this definition", naming the value and the supported identifiers.

  • New json-schema-document plugin, after OpenAPI32Plugin in the apis preset, exported as SwaggerUI.plugins.JSONSchemaDocument. It adds:
    • spec selectors isJSONSchemaDocument() and jsonSchemaDialect();
    • the component JSONSchemaDocument, which renders the resolved root schema with the json-schema-2020-12 renderer configured for the dialect and without the OpenAPI fn overrides, so OpenAPI keywords have no meaning and descriptions stay plain text;
    • a VersionPragmaFilter wrapper (document, refusal, or the OpenAPI filter unchanged);
    • a requestResolvedSubtree wrap-action that resolves a JSON Schema document at its root.
  • swagger-client's json-schema-2020-12-apidom strategy is in both strategy lists (resolve, resolveSubtree), ahead of generic. Internal, $anchor, $id-relative and external $refs resolve, and every $dynamicRef stays as written.
  • fix(spec): requestResolvedSubtree([]) stored nothing, because lodash set ignores an empty path. Nothing requested [] before, so OpenAPI resolution is unchanged.
  • Known limitation: an embedded schema resource or external file declaring another dialect renders with 2020-12 meaning (references that cross dialects are out of scope).
  • README compatibility note; CLAUDE.md plugin list and count.

Draft until the swagger-client release (swagger-api/swagger-client#4306). The branch no longer installs unreleased tarballs, so it needs a swagger-client release that includes the json-schema-2020-12-apidom strategy changes; until then CI is expected to fail. Before merging: bump swagger-client to the release and run every check again.

Motivation and Context

Step U1 of "Standalone JSON Schema 2020-12". Today a JSON Schema document gets "Unable to render this definition". SwaggerEditor's preview needs swagger-ui-react to render it natively under the key JSONSchemaDocument.

How Has This Been Tested?

  • Unit tests for detection: every identifier variant, JSON and YAML, the API description fields, a nested $schema in an embedded resource.
  • Unit tests for the selectors, wrap-action, wrapper, component and the subtree fix.
  • Playwright: rendering and $ref resolution, refusal, and an OAS 2.0/3.0/3.1/3.2 regression against ARIA snapshots recorded on main. The same regression spec checks that nested-only $schema documents and AsyncAPI 3.0 / Arazzo 1.0.1 documents with a root $schema render as before.
  • lint-errors, type-check, test:unit, full e2e, e2e:typecheck, build, test:artifact.

Checklist

My PR contains...

  • No code changes
  • Dependency changes
  • Bug fixes (requestResolvedSubtree([]))
  • Improvements
  • Features (non-breaking change which adds functionality)

My changes...

  • are breaking changes to a public API
  • are breaking changes to a private API
  • are breaking changes to a developer API
  • are not breaking changes.

Documentation

  • My changes require a change to the project documentation.
  • If yes to above: I have updated the documentation accordingly.

Automated tests

  • My changes can and should be tested by unit and/or integration tests.
  • If yes to above: I have added tests to cover my changes.
  • If yes to above: I have taken care to cover edge cases in my tests.
  • All new and existing tests passed.

🤖 Generated with Claude Code

RobertHebel and others added 5 commits October 28, 2026 13:38
requestResolvedSubtree([]) resolved the whole document and then dropped
the result: lodash's set() and fp assocPath() ignore an empty path, so
the batch wrote back only what earlier requests had stored. An empty
path now replaces the batch's result with the resolved document (when
it is an object), which is what a standalone JSON Schema document needs
to be resolved at its root.

Nothing requests an empty path today, so OpenAPI and Swagger documents
resolve exactly as before; non-empty paths keep their behaviour, which
the new unit test pins next to the empty-path cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SwaggerUI({ url }) now renders a standalone JSON Schema 2020-12 document
instead of "Unable to render this definition". A document is one when
its root $schema is https://json-schema.org/draft/2020-12/schema (an
empty fragment is normalised) and it has none of the fields openapi,
swagger, asyncapi and arazzo.

The new json-schema-document plugin, loaded after OpenAPI32Plugin in the
apis preset and exported as SwaggerUI.plugins.JSONSchemaDocument:

- spec selectors isJSONSchemaDocument() and jsonSchemaDialect();
- the JSONSchemaDocument component renders the root schema, resolved by
  swagger-client, through a json-schema-2020-12 renderer instance
  configured for the dialect (default$schema, defaultModelExpandDepth,
  the 2020-12 keywords plus swagger-client's $$ref) and none of the
  OpenAPI fn overrides, so OpenAPI keywords keep no meaning and
  descriptions stay plain text;
- a VersionPragmaFilter wrapper renders it, refuses a root $schema
  naming any other dialect with a message that names the value and the
  supported identifiers, and renders the OpenAPI filter otherwise;
- a requestResolvedSubtree wrap-action resolves a JSON Schema document
  at its root, whatever path is requested.

The swagger-client plugin lists the json-schema-2020-12-apidom strategy
in resolve and resolveSubtree, ahead of the generic strategy, so
internal, $anchor, $id-relative and external $refs are resolved and
every $dynamicRef stays as written.

OpenAPI 2.0, 3.0, 3.1 and 3.2 documents, including ones with $schema at
the root or in Schema Objects, render as before: ARIA snapshots recorded
on main pin them, together with AsyncAPI 3.0, Arazzo 1.0.1 and
nested-only $schema documents.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core §8.1.1 allows $schema only in the root of an embedded schema
resource, so the nested-only fixture and unit case now carry an $id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Embedded resources and external files declaring another dialect render
with the 2020-12 meaning (PRD D3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@robert-hebel-sb
robert-hebel-sb force-pushed the feat/json-schema-2020-12-detection branch from 9642c21 to dbf3063 Compare October 28, 2026 12:38
@robert-hebel-sb
robert-hebel-sb marked this pull request as draft October 28, 2026 12:40
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