Skip to main content

check-json5

CI codecov Python 3.10+ pre-commit License: MIT

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-json hook 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 GLOB holds chosen files to strict JSON (no comments, no NaN), for files that a JSON parser reads at runtime, such as package.json.

  • Fast path: strict JSON is parsed with the C-speed stdlib json parser, falling back to the pure-Python json5 parser only when a file actually uses JSON5 features (~500× faster on large strict-JSON files; see Performance).

  • Accepts NaN and Infinity (both parsers allow them) unless --strict covers the file.

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)

Source distribution for check-json5 1.3.0
File Size Uploaded
check_json5-1.3.0.tar.gz 12.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for check-json5 1.3.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

1.4.1

2 release files

1.4.0

2 release files

This release

1.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page