β check-json-schema: pre-commit hook
β’ 495 words β’ 3 min β’ updated
Problem statement: given an entry.json file, validate it against a given
schema.json file (for example, found via the schema
store).
I like the check-jsonschema python package:
pipx run check-jsonschema --schemafile schema.json entry.jsonWhat if we want to do the validation via a pre-commit.com hook?
repos:
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.33.2
hooks:
- id: check-jsonschema
files: ^entry\.json$
args:
- --schemafile
- schema.jsonThis approach works well, but it requires the upkeep of a mapping from JSON file to JSON schema.
If we had various JSON files within a single repository, this would result in a maintenance burden in the pre-commit config file.
For example:
repos:
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.33.2
hooks:
- id: check-jsonschema
alias: check-jsonschema-entry1
files: ^entry1\.json$
args:
- --schemafile
- schema1.json
- id: check-jsonschema
alias: check-jsonschema-entry2
files: ^entry2\.json$
args:
- --schemafile
- schema2.jsonIt’s somewhat annoying to maintain multiple entries in that fashion. Furthermore
it can easily get outdated: upon the deletion of entry1.json from the
repository, you’d need to remember to manually delete its corresponding entry
from the pre-commit config file.
Can we do better?
What if we embedded the schema reference within the JSON file itself?
For example, with a local schema:
{
"$schema": "schema.json"
}Or with a remote schema URI, via HTTPS:
{
"$schema": "https://example.com/schema.json"
}Now the JSON file is self-contained, and there’s no need to define a mapping from it to its JSON schema elsewhere.
How can we integrate this approach within pre-commit?
Initially I thought that
check-metaschema
from the check-jsonschema python package was the answer, but it turns out it
isn’t.
In fact, this isn’t currently possible. There’s a feature request, filed ~2 years ago, with no consensus yet on how move forward. Its maintainer seems helpful and concerned with backwards compatibility.
For the sake of unblocking myself, I decided to wrap the ability to do so within my own pre-commit hook definition.
This gave birth to the following repository:
thiagowfx/check-json-schema-meta, which I also announced in the original feature request thread.
Usage:
repos:
- repo: https://github.com/thiagowfx/check-json-schema-meta
rev: v0.0.2
hooks:
- id: check-json-schema-metaIt goes through each JSON file in the repository, looking for an optional
top-level $schema key. When found, the file is validated against the defined
schema.
A --strict command-line flag enforces the presence of the $schema key,
otherwise the default behavior is to skip files that do not have it.
The underlying schema validation defers the work to the same python package
first mentioned in this post. Because it uses
SchemaLoader,
both local and remote (http(s)) file references are supported.
This is the first original pre-commit hook I have written. By original I mean that I couldn’t find any pre-existing open source hook that accomplishes this task. The entire repository was developed with AI assistance (Claude Code), but I wasn’t satisfied with out-of-the-box defaults; I had to heavily modify it to shape it to my taste β which was achieved with a mix of follow-up prompting and local edits.