check-json5
A pre-commit hook that checks whether .json files parse as
JSON5 (JSON with comments, trailing commas, and more). It replaces the
standard check-json hook, accepts JSON5 too, and keeps the speed of the C parser on ordinary
JSON.
Features
-
Accepts JSON5 syntax (comments, trailing commas) that the standard
check-jsonhook rejects. -
Every failure names its place, as
file:line:col: message, so editors and terminals link straight to it. A duplicate key also gets its path, and every repeat in a file is listed:config.json:4:5: duplicate key $.server.port config.json:9:3: duplicate key $.plugins[2].name
-
On GitHub Actions, each failure is also an annotation on the line of the pull request diff.
-
--strict GLOBholds chosen files to strict JSON (no comments, noNaN), for files that a JSON parser reads at runtime, such aspackage.json. -
Fast path: strict JSON is parsed with the C-speed stdlib
jsonparser, falling back to the pure-Pythonjson5parser only when a file actually uses JSON5 features (~500× faster on large strict-JSON files; see Performance). -
Accepts
NaNandInfinity(both parsers allow them) unless--strictcovers the file.
Links
Usage
In .pre-commit-config.yaml, under repos:, add:
- repo: https://github.com/simonvanlierde/check-json5
rev: v1.3.0
hooks:
- id: check-json5
Remove the original check-json hook if it is already included. A file passes when it parses as
JSON5 and has no duplicate keys. The hook picks files by extension (.json, .jsonc, .json5,
.geojson, .jsonld), while check-json picks them by type, so files such as .babelrc or
.ipynb are no longer checked after the swap. Add them with files: if you need them.
Strict files
Some JSON files are read by a strict parser at runtime: a comment in package.json passes a JSON5
check and then breaks npm. Name those files with --strict. Each pattern matches the file name
at any depth, or the whole path when it contains a /. * also matches across /. A leading !
exempts files, and the last matching pattern wins:
- id: check-json5
args: [--strict, "*.json", --strict, "!tsconfig*.json", --strict, "!.vscode/*"]
Without pre-commit
The hook is also a command on PyPI:
uvx check-json5 --strict package.json config/*.json
Introduction
JSON5 is similar to JSON but permits comments, trailing commas, and more. It resembles "JSONC" (JSON
with Comments) but, unlike JSONC, has an actual specification. Many config files in the wild are
really JSON5, so the standard check-json hook, which rejects comments outright, flags them as
invalid. This hook accepts them.
Strict-JSON files are parsed with the fast built-in json
library; only files that use JSON5 features fall back to the pure-Python
json5 library.
Performance
The pure-Python json5 parser is slow on large files. Since most .json files are strict JSON, the
hook tries the C-speed stdlib json parser first and only falls back to json5 when a file uses
comments or trailing commas. Duplicate-key detection works on both paths.
Time for one hook call per file (strict JSON, taking the fast path), best of 10 runs of
uv run python scripts/bench.py on 2026-10-11 (Intel i9-14900KF, Linux, Python 3.13.7, json5 0.15.0,
load average 1.5):
| File size | Before (json5 only) |
After (fast path) | Speedup |
|---|---|---|---|
| 1 KB | 2.5 ms | 0.02 ms | ~100× |
| 47 KB | 123 ms | 0.19 ms | ~660× |
| 483 KB | 1.3 s | 1.8 ms | ~750× |
| 2 MB | 5.4 s | 7.7 ms | ~700× |
The script generates its fixture files in a temporary directory, so nothing large is committed. Timings vary between runs by up to 2× on a loaded machine. The 1 KB fast-path time is close to the timer's resolution, so its speed-up ranged from ~80× to ~100× across runs.
To time whole hook runs instead, run bash scripts/bench.sh (needs
hyperfine). It times the hook against the json5 parser
on 50 KB, 500 KB and 2 MB files and prints one table; --quick times the 50 KB file once. Each
run includes about 20 ms of Python startup, so its speed-ups are smaller than the ones above.
Files that use JSON5 syntax still go through the json5 parser and are unchanged. For tiny config
files the absolute saving is negligible next to Python's own startup cost; the win matters on large
JSON files.
Development
The project uses uv for dependency management, pytest for
tests, pre-commit for local checks, and GitHub Actions for CI with coverage reported to Codecov.
uv sync # install dependencies
uv run pytest # run the test suite
uv run pytest --cov # tests with coverage
uv run pre-commit run -a # run the configured hooks locally
Credits
Adapted by Simon van Lierde from the original check-json5 by Ben Mares, itself based on the pre-commit-hooks repository by Anthony Sottile and contributors. This version switches dependency management from Poetry to uv and adds the fast-path parser and benchmark above.
License
MIT, consistent with the upstream projects it is based on (Ben Mares, pre-commit-hooks).
Metadata
Release files for check-json5 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| check_json5-1.3.0.tar.gz | 12.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| check_json5-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.9 kB
Release files / check_json5-1.3.0.tar.gz
| Download URL | check_json5-1.3.0.tar.gz |
|---|---|
| Size | 12.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6bf6a17e390010fe442b491bf4e202ee3476c3569112abecd7a975f426f2c72b
|
|
BLAKE2b-256 checksum How to use checksums |
9eff26f7a589a8e13bebff822a4c091afee6cca8a466be92f02def1011d6d6bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / check_json5-1.3.0-py3-none-any.whl
| Download URL | check_json5-1.3.0-py3-none-any.whl |
|---|---|
| Size | 9.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f8abdace02ebaadff0c15d37a08c82565c222c04ba6848c5e224ec3f8c73960b
|
|
BLAKE2b-256 checksum How to use checksums |
c573e1e150c7ee056b076c2238026e07600f0dd3ecf2b2c5dc80b530150dd4dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log