Skip to content

fix: support content and OpenAPI keywords - #296

Merged
jdesrosiers merged 6 commits into
hyperjump-io:mainfrom
MohitSAGAR11:fix/content-keywords
Nov 1, 2026
Merged

jdesrosiers merged 6 commits into
hyperjump-io:mainfrom
MohitSAGAR11:fix/content-keywords

Conversation

@MohitSAGAR11

@MohitSAGAR11 MohitSAGAR11 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Closes #294

Summary

A schema that uses a keyword the package doesn't know about makes jsonSchemaErrors throw Encountered unsupported keyword .... This adds support for the keywords the standard dialects and the OpenAPI dialects can put in the AST.

Content keywords (draft-07 and up)

contentMediaType, contentEncoding, and contentSchema are annotation-only, but they weren't registered. They're now registered as annotations, alongside comment, default, description, and examples.

OpenAPI keywords

The OpenAPI dialects define their own keyword URIs:

  • The annotation-only keywords discriminator, example, externalDocs, xml, and nullable (OpenAPI 3.0) don't affect validation and are registered as annotations.
  • The OpenAPI 3.0 type keyword asserts types like the standard type keyword, so the type/const/enum error handler now recognizes it and produces the same messages (including the null type added by nullable).

OpenAPI 3.1 and 3.2 reuse the same keyword URIs, so they're covered too.

Tests

  • src/test-suite/tests/content.json — the content keywords are annotations across draft-07, 2019-09, and 2020-12.
  • src/openapi.test.js — OpenAPI 3.0/3.1/3.2 type assertions, nullable, annotation keywords, and annotation-only schemas.

npm test (1338 passing), npm run lint, and npm run type-check all pass.

@MohitSAGAR11 MohitSAGAR11 changed the title fix: register content keywords as annotations fix: support content and OpenAPI keywords Oct 19, 2026
@MohitSAGAR11
MohitSAGAR11 marked this pull request as ready for review October 19, 2026 01:35
@MohitSAGAR11

Copy link
Copy Markdown
Contributor Author

Hi @jdesrosiers, thanks again for the quick reply on #294.

While this PR is up, I wanted to check in: is there anything you'd like help with, or a direction you'd prefer I work toward? I'm happy to keep doing what I've been doing — finding and reporting issues, then opening a PR for the ones you approve — but I didn't want to assume. Let me know what would be most useful.

@jdesrosiers jdesrosiers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good so far. Please move openapi.test.js to use the JSON-based test suite.

The contentMediaType, contentEncoding, and contentSchema keywords are annotation-only, but they weren't registered, so any schema using them threw 'Encountered unsupported keyword'. Register them as annotations like the other annotation keywords.

Closes hyperjump-io#294
The OpenAPI dialects use their own keyword URIs, so any schema using them threw 'Encountered unsupported keyword'. Register the annotation-only keywords (discriminator, example, externalDocs, nullable, xml) and teach the type/const/enum error handler about the OpenAPI 3.0 type keyword so it produces the same messages as the standard type keyword.
@MohitSAGAR11

Copy link
Copy Markdown
Contributor Author

Thanks! I moved the OpenAPI tests to the JSON test suite and removed openapi.test.js.

  • OpenAPI 3.1 and 3.2 now run the whole tests suite. They all pass as-is since both dialects are based on 2020-12.
  • OpenAPI 3.0 only supports a subset of the keywords, so the OpenAPI-specific tests are in a new src/test-suite/openapi/ folder that runs against all three OpenAPI dialects. compatibility there uses 30, 31, and 32, for example "=30" for nullable. I added a short section about it to the test-suite README.

I also rebased on main. If you'd prefer the OpenAPI tests organized differently, let me know and I'll change it.

@MohitSAGAR11

Copy link
Copy Markdown
Contributor Author

@jdesrosiers just a gentle ping on this one. I moved the OpenAPI tests into the JSON test suite like you asked. Let me know if you'd like anything changed.

jdesrosiers and others added 3 commits October 31, 2026 20:41
Error handlers that look up the type keyword by URI, such as anyOf and oneOf, missed the OpenAPI 3.0 type keyword, so they didn't drop alternatives with the wrong type. Add an alias option to keyword definitions so the normalizer reports a keyword's results under another keyword's URI, and make the OpenAPI 3.0 type keyword an alias of type. This replaces the special case in the type/const/enum error handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenAPI 3.0 only ran the openapi tests, so its type keyword was never tested inside keywords like anyOf, oneOf, and enum. Run the main tests against it as draft-04 and skip the tests with schemas that aren't valid OpenAPI 3.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each OpenAPI dialect was run twice, once for the tests folder and once for the openapi folder, with different dialect numbers in each and two describe blocks with the same name. Run each dialect once over both folders, numbered by the JSON Schema release it's based on: 4 for OpenAPI 3.0 and 2020 for OpenAPI 3.1 and 3.2. Also rename the parsed test suite so it doesn't shadow the folder name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@jdesrosiers jdesrosiers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up going a slightly different direction. I changed it to make the OpenAPI 3.0 type keyword an alias of type, so every error handler sees it, not just type/const/enum. The way it was, anyOf and oneOf didn't drop alternatives of the wrong type under 3.0.

@jdesrosiers
jdesrosiers merged commit 3fede17 into hyperjump-io:main Nov 1, 2026
1 check passed
@MohitSAGAR11

Copy link
Copy Markdown
Contributor Author

Thanks for merging, and for the fixes! Making it an alias of type is much cleaner. I only handled it in the type/const/enum handler and missed that anyOf/oneOf use the type to drop alternatives. Running the main suite against 3.0 also checks that every handler sees it. Next time a dialect redefines a standard keyword, I'll alias it instead of special-casing handlers.

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.

contentMediaType, contentEncoding and contentSchema throw "unsupported keyword"

2 participants