Skip to main content

jsonvet

CI codecov pre-commit License: MIT release

jsonvet checks JSON, I-JSON, JSONC, HuJSON (JWCC), JSON5 and JSON Lines files for syntax errors, duplicate keys and the rules of each dialect. Every problem comes with its file, line, column and rule, and a duplicate key with the JSONPath and position of both copies:

config.json:4:5: error[duplicate-key] duplicate key $.server.port (first at 2:5)
package.json:3:1: error[syntax] comments are not allowed in json
events.jsonl:12:1: error[syntax] blank line; JSON Lines needs a value on every line

It is a pre-commit and prek hook, a command, and a Rust library. Until 2.0 it was check-json5, a Python hook; 2.0 is a rewrite in Rust that keeps its verdicts (see Coming from check-json5).

Use it as a hook

In .pre-commit-config.yaml (pre-commit or prek):

- repo: https://github.com/simonvanlierde/jsonvet
  rev: v2.0.0
  hooks:
    - id: jsonvet

The hook installs a prebuilt binary from PyPI, so it needs no Rust. It checks files by name: .json, .jsonc, .json5, .jsonl, .ndjson, .geojson, .jsonld, .hujson, .jwcc, .code-workspace, .code-snippets, .webmanifest and .babelrc. In GitHub Actions each problem also becomes an annotation on the pull request.

Dialects

Each file is checked in the dialect its extension implies, and --dialect or the config file can choose another. Each step in JSON, JSONC, JWCC, JSON5 only adds syntax to the one before.

Dialect Adds to JSON Default for
json nothing (RFC 8259) none; choose it with --dialect or --strict
i-json stricter content (RFC 7493): lone surrogates, noncharacters and numbers a double cannot hold are errors none
jsonc // and /* */ comments .jsonc, .code-workspace, .code-snippets
jwcc comments and trailing commas (HuJSON) .hujson, .jwcc
json5 the JSON5 1.0.0 grammar .json, .json5, .geojson, .jsonld, .webmanifest, .babelrc
jsonl one JSON value per line (JSON Lines) .jsonl, .ndjson

.json files default to JSON5, because most .json files that fail as JSON are config files with comments. Hold the ones a strict parser reads, such as package.json, to JSON with --dialect json:package.json.

Rules

Rule Reports Default
syntax the first syntax error; checking stops there error
duplicate-key a key repeated in one object, with both positions and its path error
invalid-number a number a double cannot hold, or an integer past ±(2⁵³ − 1) error in i-json, off elsewhere
invalid-code-point a lone surrogate or a noncharacter in a string error in i-json, off elsewhere
byte-order-mark a byte order mark at the start of the file warning in json and i-json, error in jsonl
missing-final-newline a JSON Lines file that does not end with a newline warning in jsonl

Warnings don't fail a run unless there are more than --max-warnings N.

Options and configuration

--dialect DIALECT[:GLOB]   check files matching GLOB (every file, without one) as DIALECT,
                           or as `auto`, the extension's default; the last match wins
--strict GLOB              the same as --dialect json:GLOB, kept from check-json5
--error RULE, --warn RULE, --ignore RULE
--max-warnings N
--config FILE, --no-config

A glob without / matches the file name at any depth, and one with / matches the whole path. * also matches /. Paths are matched as given on the command line, so relative to the working directory, even for globs from a config file; pre-commit runs from the repository root.

Settings can also live in jsonvet.toml, or in a [tool.jsonvet] table in pyproject.toml. jsonvet looks in the working directory and its parents up to the repository root, and the command line wins:

rules = { byte-order-mark = "ignore", missing-final-newline = "error" }

# Checked in order; the last matching entry wins.
dialects = [
  { files = ".vscode/*.json", dialect = "jsonc" },
  { files = "package.json", dialect = "json" },
]

Exit status: 0 when no file has an error, 1 when one does, 2 for a usage error.

Other ways to run it

uvx jsonvet config/*.json        # from PyPI, without installing
pip install jsonvet              # the same binary, as a Python package
cargo install jsonvet-cli        # from source

The library is the jsonvet crate:

use jsonvet::{check, Config, Dialect};

let report = check("{\"a\": 1, \"a\": 2}", &Config::new(Dialect::Json));
for problem in report.problems() {
    let at = report.location(problem.offset());
    println!("{}:{}: {}[{}] {problem}", at.line, at.column, problem.severity(), problem.rule());
}

Coming from check-json5

Bump rev to v2.0.0. The check-json5 hook id, the check-json5 command and --strict keep working until 3.0, and the check-json5 package on PyPI now installs jsonvet.

2.0 gives the same pass or fail as 1.4.1 for every file, the same exit codes and the same duplicate-key paths. Comparing both on 20,114 generated files in JSON5 and in strict mode, 40,228 runs in all, they agree on every one. What changes, and why, is listed in the CHANGELOG and in docs/design.md:

  • each line gains the severity and rule, as in error[duplicate-key], and syntax errors use jsonvet's own wording;
  • the hook also checks .jsonl and .ndjson files;
  • lines end at every JSON5 line terminator (LF, CR, CRLF, U+2028, U+2029), so positions after a lone CR or U+2028 differ;
  • the importable Python module is gone; the wheel brings the jsonvet and check-json5 commands.

Speed

Median wall time of one run over the files, from uv run scripts/bench.py on 12 cores of a Ryzen 7 H 255 under Linux. Both tools give the same verdict in every case:

Case check-json5 1.4.1 jsonvet 2.0 Speed-up
1,100 config files 40 ms 12.5 ms 3x
2.7 MB JSON 41 ms 9.8 ms 4x
2.7 MB JSON, duplicate key 330 ms 11.6 ms 29x
120 KB JSONC 22 ms 1.5 ms 15x
1.8 MB JSON5 11,641 ms 8.3 ms 1,398x

1.4 sent JSON, and JSONC with its comments stripped, to Python's C parser, so those were already fast. Any other JSON5 syntax went to a pure-Python parser, and so did the second pass that finds a duplicate key's position. jsonvet does everything in one pass of one parser.

How it is tested

  • the json5-tests suite, all 114 cases;
  • a reviewed snapshot of edge cases in every dialect;
  • property tests: no input makes it panic, every position lies on a character boundary and matches a naive recount;
  • fuzzing with cargo-fuzz, against serde_json and the json5 crate as references;
  • the file-by-file comparison with check-json5 1.4.1 above, in CI;
  • CI on Linux, macOS and Windows, plus the oldest supported Rust (1.88).

Development

cargo test --workspace                         # tests, including json5-tests (git submodule)
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all
uv run scripts/differential.py                 # compare with check-json5 1.4.1
uv run scripts/bench.py                        # time against check-json5 1.4.1
cargo +nightly fuzz run check                  # fuzzing, from fuzz/

Clone with --recurse-submodules, or run git submodule update --init for the test suite.

Credits

I (Simon van Lierde) started this as a fork of check-json5 by Ben Mares, which is based on the pre-commit-hooks repository by Anthony Sottile and contributors. 2.0 is a rewrite in Rust.

License

MIT, like the projects it started from (Ben Mares, pre-commit-hooks).

Metadata

Release files for jsonvet 2.0.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 jsonvet 2.0.0
File Size Uploaded
jsonvet-2.0.0.tar.gz 48.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for jsonvet 2.0.0
File
jsonvet-2.0.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
jsonvet-2.0.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
jsonvet-2.0.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
jsonvet-2.0.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
jsonvet-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
jsonvet-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
jsonvet-2.0.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
jsonvet-2.0.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 4.8 MB

Release files / jsonvet-2.0.0.tar.gz

Download URL jsonvet-2.0.0.tar.gz
Size 48.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3b74a6c770421ced56dc4a7e9f7b9afdfa4d3d44dc8faa635f8bf5f91159b75e
BLAKE2b-256 checksum
How to use checksums
0e111c73abef71c3d59e39f1cfdc8bb5107fce857dbebead0ddeb538c37c61e8
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 / jsonvet-2.0.0-py3-none-win_arm64.whl

Download URL jsonvet-2.0.0-py3-none-win_arm64.whl
Size 426.9 kB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
20ca65b4a4d39d5d3197bb7a1056a53cc435022f63f31dbbd588d8551059eced
BLAKE2b-256 checksum
How to use checksums
4fb28e6c6f89d3aaa2801a8aab87c248f3b6542dc26853d3450f9f348cf6c48b
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 / jsonvet-2.0.0-py3-none-win_amd64.whl

Download URL jsonvet-2.0.0-py3-none-win_amd64.whl
Size 458.8 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
c6ac0bdd5a63c25357d310f8029fc9eb29c450215e34f1858079877e661b3bb1
BLAKE2b-256 checksum
How to use checksums
2c5a4c5677262e5e2c4f8c1a2103b3a2e7e5f8d361e6a6cf95159528d5503e49
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 / jsonvet-2.0.0-py3-none-musllinux_1_2_x86_64.whl

Download URL jsonvet-2.0.0-py3-none-musllinux_1_2_x86_64.whl
Size 721.7 kB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
d8297623d4a7dbb4a321891830ea8969e18386a3047dc764ab58b12c22b7817c
BLAKE2b-256 checksum
How to use checksums
d30abc7421a0abe7b175136f58d7b2c08d59cf40d5c7b8a4f018676095d515d4
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 / jsonvet-2.0.0-py3-none-musllinux_1_2_aarch64.whl

Download URL jsonvet-2.0.0-py3-none-musllinux_1_2_aarch64.whl
Size 677.5 kB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
393cbcf5240a7d321c5428aea1ce849fedbd6880f54dfe65f29f02f702f4a4fa
BLAKE2b-256 checksum
How to use checksums
f9dd85e138381a0eacd9d068c0ba24131123da2a09166955a5cba61c7289f394
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 / jsonvet-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL jsonvet-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 630.6 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
c09e53fb85fb66744787bc96226f9fdd360c39744219df37991d04c637f34c75
BLAKE2b-256 checksum
How to use checksums
6336a2db64e70195413880282c5f3dda50c85a7d78fe2698ceceea46d60575b3
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 / jsonvet-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL jsonvet-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 591.5 kB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
da227e597c34a0a91379d0ee09d541f34b977d7ed639e4e4899484d3bf7a0d0a
BLAKE2b-256 checksum
How to use checksums
39ff59ce59ff1f91f554bb81e2d56c1f3ce4e88a0bc9c78b61f2cdabd79487f5
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 / jsonvet-2.0.0-py3-none-macosx_11_0_arm64.whl

Download URL jsonvet-2.0.0-py3-none-macosx_11_0_arm64.whl
Size 573.4 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ce8bb386cd838527bc785a8025118ce59850f154b5d7fcc0fa95cb5d25424625
BLAKE2b-256 checksum
How to use checksums
2f9965dd1e54dd65faaecdffaf1753a2cdf87d306c8caa7936068c280d0b3fad
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 / jsonvet-2.0.0-py3-none-macosx_10_12_x86_64.whl

Download URL jsonvet-2.0.0-py3-none-macosx_10_12_x86_64.whl
Size 623.7 kB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
c5bb8a72dbfa3d9421143b952fef196947f15cc4aff67ef7597ddd586df3d866
BLAKE2b-256 checksum
How to use checksums
1909ec2f1983a26c9fb7234001b7f8ed3f042979818ea532d75e9b3381a64dca
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

3.0.0

9 release files

This release

2.0.0 This release

9 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