- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| new_schema_breaking.json | ||
| new_schema_compatible.json | ||
| old_schema.json | ||
| README.md | ||
| schema_diff.py | ||
json-schema-diff
A JSON Schema breaking-change detector, built for API versioning.
Compares two JSON Schema documents (old vs. new) and classifies every difference as BREAKING, compatible, or info — so you can catch an accidental breaking change to your API contract before you ship it, instead of finding out from an angry integration partner.
Zero dependencies (Python stdlib only — json + argparse), no network
calls, works entirely offline. Supports the common subset of JSON Schema
(draft-07 / 2020-12) actually used in real API schemas: type,
properties, required, additionalProperties, enum, items, format,
minimum/maximum, minLength/maxLength, minItems/maxItems, pattern.
What it catches
- Type narrowing —
["string","integer"]->"string"(BREAKING), or a straight incompatible type swap (BREAKING) - Newly-required fields — a field that used to be optional is now required; existing producers that omit it will fail validation (BREAKING)
- Removed required fields — a required field disappears entirely; any consumer depending on it breaks (BREAKING)
additionalPropertiestightened tofalse— previously-accepted extra fields get rejected (BREAKING)- Enum values removed — previously-valid values now rejected (BREAKING)
- Numeric/length constraints narrowed —
minimumraised,maximumlowered,maxLengthshortened, etc. (BREAKING); the reverse relaxations are flagged as compatible - Pattern changed — treated conservatively as BREAKING unless it's unchanged, since proving one regex is a strict superset of another is out of scope for a stdlib tool
- Everything with the opposite effect (new optional fields, relaxed constraints, added enum values, widened types, removed constraints) is classified compatible
formathint changes are info-only, since most validators only warn on format anyway
Usage
./schema_diff.py old_schema.json new_schema.json
./schema_diff.py old_schema.json new_schema.json --json
./schema_diff.py old_schema.json new_schema.json --fail-on-breaking # CI gate
Exit codes: without --fail-on-breaking, always exits 0 (safe to run
informationally without gating a build). With --fail-on-breaking, exits
1 if any BREAKING finding is present. Exits 2 on a usage/parse error.
Why this exists
Most API teams find out about a breaking schema change when a downstream
consumer's integration starts failing in production — usually days after
the change shipped, and often traced back to something as small as a field
quietly becoming required or an enum value getting dropped. Running this
in CI against the last-released schema and the current one turns that into
a merge-time check instead of a customer-facing incident.