Skip to content

[feat] json: validate/try_validate — JSON Schema validation#159

Merged
vt128 merged 2 commits into
masterfrom
json-validate
Jun 13, 2026
Merged

[feat] json: validate/try_validate — JSON Schema validation#159
vt128 merged 2 commits into
masterfrom
json-validate

Conversation

@vt128

@vt128 vt128 commented Jun 13, 2026

Copy link
Copy Markdown
Member

What

Adds json.validate / json.try_validate to lib/json (the fourth v0.2.1 increment; resolves the PKG-19 need inside the json module per user decision): check a document against a JSON Schema — drafts 4/6/7/2019-09/2020-12, auto-detected from $schema (default 2020-12). data and schema each accept a JSON string/bytes or a Starlark value, so a schema can be written as a dict literal.

  • validate(data, schema)None, or fails with one line per violation, each carrying the JSON Pointer of the offending location: at /age: must be >= 0 but found -3.
  • try_validate(data, schema) → three distinguished outcomes: (True, None) valid · (False, details) invalid · (None, error) could-not-run (bad schema / malformed JSON / bad args).

Engine & license decision

github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 as a module dependency — deliberately not vendored: copying Apache-2.0 source into this MIT repository would make it mixed-license. As a module dep the repo stays pure MIT (CLAUDE.md now records this rule: vendoring is same-license/MIT only; differently-licensed permissive libraries go through the module-dependency evaluation bar).

Evaluation (all on the go1.19 floor, per the bar):

dimension measured
dependency floor its go.mod is exactly go 1.19 — does not lift ours
transitive deps zero (no require block) → go.sum gains exactly 2 lines
binary delta +256 KiB (7,536,640 → 7,798,784 B, −trimpath −s −w, golang:1.19 Docker) — under the +312 KiB the module survey accepted for this capability
hand-written DSL stays rejected per the survey (reinventing JSON Schema, loses OpenAPI interop)

Purity & stability

  • All external $ref loading is blocked (file:// and network) via the Compiler's LoadURL hook — schemas must be self-contained; the json module stays CapPure.
  • Panic audit of the engine: 9 panic sites, none script-reachable — Must* helpers are init-only and unused; Validate recovers InfiniteLoopError/InvalidJSONTypeError into errors (and the wrapper handles any non-ValidationError error); the rest are non-script invariants. Backed by hostile-input tests: self-referential $ref, invalid pattern regex, 200-deep nesting, uniqueItems hashing — error, never panic.
  • Compiled schemas are cached (bounded at 64, dropped wholesale on overflow) so scripts cannot grow memory unboundedly; repeated validation against the same schema text has zero recompilation cost.

Tests / verification

A TestJSONValidate section in json_test.go (no new file, no third-party test framework): conforming/violating documents, pointer-carrying messages, the three try_ outcomes, schema-as-dict, draft-7 via $schema, blocked file/http $refs, cache-eviction churn, the violation-list cap, robustness cases, and argument errors. validate.go functions at 93–100%; gofmt/vet clean; full-repo -race -count=2 and the go1.19 floor (Docker) green.

Refs: PKG-19 / D6 (module survey: Schema validate 必做, hand-written DSL rejected); v0.2.1 increment #4.

vt128 and others added 2 commits June 13, 2026 09:41
Adds json.validate / json.try_validate to lib/json (the fourth v0.2.1
increment; resolves the PKG-19 need inside the json module per user
decision): check a document against a JSON Schema, drafts 4/6/7/2019-09/
2020-12 auto-detected from $schema. data and schema each accept a JSON
string/bytes or a Starlark value, so a schema can be written as a dict
literal. validate returns None or fails with one line per violation,
each prefixed with the JSON Pointer of the offending location
("at /age: must be >= 0 but found -3"). try_validate distinguishes three
outcomes: (True, None) valid, (False, details) invalid, (None, error)
when validation could not run.

Engine: github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 as a module
dependency — a deliberate, evaluated exception to the vendoring pattern:
its go.mod is exactly go1.19 with ZERO requirements, so go.sum gains two
lines and no transitive deps; Apache-2.0; measured +256 KiB on the
go1.19 floor (Docker, -trimpath -s -w), under the +312 KiB the module
survey already accepted for this capability. Hand-written validation
DSLs stay rejected per that survey.

Purity and stability: all external $ref loading (file:// and network) is
blocked via the Compiler's LoadURL hook — schemas must be self-contained.
A panic audit of the engine found no script-reachable panic (Must*
helpers are init-only and unused; Validate recovers InfiniteLoopError/
InvalidJSONTypeError into errors, which the wrapper also handles), backed
by hostile-input tests: self-referential $ref, invalid pattern regex,
200-deep nesting, uniqueItems hashing — error, never panic. Compiled
schemas are cached (bounded, dropped wholesale on overflow so scripts
cannot grow memory unboundedly).

Tests are a section in json_test.go (no new file, no third-party test
framework): conforming/violating documents, pointer-carrying messages,
the three try_ outcomes, draft-7 via $schema, blocked $refs, cache
eviction churn, the violation-list cap, and argument errors.
-race -count=2 and the go1.19 floor are green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…differently-licensed permissive deps go through the module-dependency evaluation bar

Records the jsonschema decision rationale: vendoring Apache-2.0 source
into this MIT repository would make it mixed-license, so the engine is a
module dependency instead — acceptable because its go.mod is exactly
go1.19, it has zero requirements, and the binary delta measured +256 KiB
on the floor toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codacy-production

codacy-production Bot commented Jun 13, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 11 minor

Results:
11 new issues

Category Results
BestPractice 1 minor
CodeStyle 10 minor

View in Codacy

🟢 Metrics 30 complexity · 7 duplication

Metric Results
Complexity 30
Duplication 7

View in Codacy

🟢 Coverage 96.00% diff coverage · +0.01% coverage variation

Metric Results
Coverage variation +0.01% coverage variation (-1.00%)
Diff coverage 96.00% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (9749926) 7603 7192 94.59%
Head commit (74389cf) 7692 (+89) 7277 (+85) 94.60% (+0.01%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#159) 100 96 96.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jun 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.18072% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.41%. Comparing base (9749926) to head (74389cf).

Files with missing lines Patch % Lines
lib/json/validate.go 94.28% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #159      +/-   ##
==========================================
+ Coverage   93.39%   93.41%   +0.01%     
==========================================
  Files          48       49       +1     
  Lines        6105     6177      +72     
==========================================
+ Hits         5702     5770      +68     
- Misses        256      258       +2     
- Partials      147      149       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vt128 vt128 merged commit 512d891 into master Jun 13, 2026
12 checks passed
@vt128 vt128 deleted the json-validate branch June 13, 2026 01:46
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.

1 participant