feat(std/json-schema): validate JSON against the in-place keywords of 2020-12 #436

Merged
argus merged 3 commits from loop/434-json-schema into main 2026-10-23 16:07:23 +00:00
Collaborator

Closes #434

Task: step 1 of #80, std/json-schema validates JSON against the in-place keywords of JSON Schema 2020-12.

What

  • JsonSchema.read(text) / JsonSchema.parse(value) read a 2020-12 schema into a value; validate(instance) answers a Validation with one ValidationError per failed keyword (keyword, schema location, instance location as a JSON Pointer such as /items/2/name, message).
  • All listed keywords are validated; annotation keywords are read and kept; unknown keywords are ignored.
  • Refused by name with a JsonSchemaError: another $schema, $ref / $dynamicRef / unevaluatedItems / unevaluatedProperties, and a pattern RE2 does not run.
  • The JSON-Schema-Test-Suite (MIT, release 23.1.0) is vendored as the generated std/json-schema/tests/suite-cases.trb (694 cases, notice in the header). Each case is its own test. Files about $ref, $dynamicRef, unevaluated*, format, content, vocabulary, optional/ (with bignum) are left out by name; two groups that mix in a later-step keyword are listed in the test with their reason and asserted to be refused.
  • Page docs/standard-library/json-schema.md, index entry, regenerated skills/, ROADMAP Formats item notes the package as started.
  • seed/ is not touched.

Test

Locally with the nightly VM: torb test std/json-schema (718 passed), torb check std/json-schema, torb doc --check --no-run std/json-schema, torb docs index --check, torb docs skill --check, torb format --check on the touched files, tools/check-commits.sh origin/main. Tier A gates run in forge CI.

Closes #434 Task: step 1 of #80, `std/json-schema` validates JSON against the in-place keywords of JSON Schema 2020-12. ## What - `JsonSchema.read(text)` / `JsonSchema.parse(value)` read a 2020-12 schema into a value; `validate(instance)` answers a `Validation` with one `ValidationError` per failed keyword (keyword, schema location, instance location as a JSON Pointer such as `/items/2/name`, message). - All listed keywords are validated; annotation keywords are read and kept; unknown keywords are ignored. - Refused by name with a `JsonSchemaError`: another `$schema`, `$ref` / `$dynamicRef` / `unevaluatedItems` / `unevaluatedProperties`, and a pattern RE2 does not run. - The JSON-Schema-Test-Suite (MIT, release 23.1.0) is vendored as the generated `std/json-schema/tests/suite-cases.trb` (694 cases, notice in the header). Each case is its own test. Files about `$ref`, `$dynamicRef`, `unevaluated*`, `format`, `content`, `vocabulary`, `optional/` (with `bignum`) are left out by name; two groups that mix in a later-step keyword are listed in the test with their reason and asserted to be refused. - Page `docs/standard-library/json-schema.md`, index entry, regenerated `skills/`, ROADMAP Formats item notes the package as started. - `seed/` is not touched. ## Test Locally with the nightly VM: `torb test std/json-schema` (718 passed), `torb check std/json-schema`, `torb doc --check --no-run std/json-schema`, `torb docs index --check`, `torb docs skill --check`, `torb format --check` on the touched files, `tools/check-commits.sh origin/main`. Tier A gates run in forge CI.
JsonSchema.read reads a draft 2020-12 schema into a value and validate checks a JsonValue against it, answering one ValidationError per failed keyword with its schema location and its instance location as a JSON Pointer. The in-place keywords are validated; $ref, $dynamicRef, unevaluated*, another $schema and a pattern outside RE2 are refused by name with a JsonSchemaError. The cases of the JSON-Schema-Test-Suite (MIT, release 23.1.0) for these keywords are vendored as a generated suite-cases.trb and each passes.

Refs #434
docs(std/json-schema): add the std/json-schema page and note the package in the roadmap
Some checks failed
ci / commit messages (pull_request) Successful in 3s
ci / what the change touches (pull_request) Successful in 3s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap (linux-x64) (pull_request) Successful in 2m12s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m29s
ci / tier A (linux-x64) (pull_request) Failing after 5m1s
ci / gates (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
b1193741b3
The page explains reading, the keywords, what is refused and the declarations. It is listed in the standard library index, skills/ is regenerated, and ROADMAP's Formats item notes the package as started without claiming the epic done.

Refs #434
docs(std/json-schema): declare validate in its extend block as the declarations gate writes it
All checks were successful
ci / commit messages (pull_request) Successful in 3s
ci / what the change touches (pull_request) Successful in 3s
pdisc / pdisc (pull_request) Successful in 8s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 0s
ci / bootstrap (linux-x64) (pull_request) Successful in 2m9s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m12s
ci / tier A (linux-x64) (pull_request) Successful in 4m54s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m53s
ci / pack the seed (pull_request) Successful in 9s
ci / every host emits the same C (pull_request) Successful in 4m48s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
432241278d
Refs #434
argus approved these changes 2026-10-23 16:07:22 +00:00
argus left a comment

Approved at 432241278d.

  • Tests: ok. 694 vendored suite cases (release 23.1.0, MIT notice in the header), each its own test, plus json-schema.test.trb for locations, escaping, refusals and annotations. Exclusions are listed with reasons and asserted to be refused. CI green on this head (tier A, gates, pdisc, commit messages).
  • Correctness: ok. Keyword walk, contains/minContains/maxContains, prefixItems/items, additionalProperties and oneOf match 2020-12. Pointer escaping applied to property names.
  • Scope = task: ok. Matches #434 (step 1 of #80); seed/ untouched. Refusals of other $schema, $ref/$dynamicRef/unevaluated* and non-RE2 patterns are by name, so a schema is never answered "valid" unchecked.
  • Security/data/architecture: ok. No secrets, no new external dependency, patterns run on RE2 (linear time). New package, no existing boundary re-wired.
  • Docs: ok. Page, index entry, regenerated skills/, ROADMAP note; pdisc green.

Non-blocking:

  1. Validation and schema reading recurse without a depth limit, so a very deeply nested schema or document could exhaust the stack. Worth a follow-up note when $ref lands.
Approved at 432241278d. - Tests: ok. 694 vendored suite cases (release 23.1.0, MIT notice in the header), each its own test, plus `json-schema.test.trb` for locations, escaping, refusals and annotations. Exclusions are listed with reasons and asserted to be refused. CI green on this head (tier A, gates, pdisc, commit messages). - Correctness: ok. Keyword walk, `contains`/`minContains`/`maxContains`, `prefixItems`/`items`, `additionalProperties` and `oneOf` match 2020-12. Pointer escaping applied to property names. - Scope = task: ok. Matches #434 (step 1 of #80); `seed/` untouched. Refusals of other `$schema`, `$ref`/`$dynamicRef`/`unevaluated*` and non-RE2 patterns are by name, so a schema is never answered "valid" unchecked. - Security/data/architecture: ok. No secrets, no new external dependency, patterns run on RE2 (linear time). New package, no existing boundary re-wired. - Docs: ok. Page, index entry, regenerated `skills/`, ROADMAP note; pdisc green. Non-blocking: 1. Validation and schema reading recurse without a depth limit, so a very deeply nested schema or document could exhaust the stack. Worth a follow-up note when `$ref` lands.
argus merged commit 7ed30da980 into main 2026-10-23 16:07:23 +00:00
argus deleted branch loop/434-json-schema 2026-10-23 16:07:23 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!436
No description provided.