Skip to content

Releases: simonvanlierde/jsonvet

jsonvet 3.0.0

Choose a tag to compare

@simonvanlierde simonvanlierde released this 19 Oct 00:44
683c712

3.0 checks files against a JSON Schema and puts each error at its line and column, in every dialect, comments and JSON5 included. It also writes SARIF for GitHub code scanning, and it ships as a GitHub Action.

Upgrade

Set rev: v3.0.0 in .pre-commit-config.yaml, or uses: simonvanlierde/jsonvet@v3. Most hook users need nothing else. Check the breaking changes below if you run jsonvet from a directory other than its config file's, pass it unknown options from a script, match its paths in a script, or use the Rust library.

What's new

  • --schema FILE: checks each file against one JSON Schema, offline. Errors come under the rule schema, at the line and column of the value, with its JSONPath: server.json5:3:9: error[schema] "80" is not of type "integer" (at $.port). It is in every build, the hook and the Action included.
  • --format sarif: one SARIF 2.1.0 document for GitHub code scanning, with the same exit codes as text.
  • A GitHub Action: uses: simonvanlierde/jsonvet@v3 checks the repository's tracked JSON files, or the files you give it, on Linux, macOS and Windows runners. With sarif: it also writes a SARIF file for code scanning.
  • Safer output: file names and messages escape control, bidi and invisible characters, so a file name cannot forge a GitHub annotation or reorder a terminal line.
  • A DOI: each release from this one on gets a Zenodo DOI, and CITATION.cff says how to cite jsonvet.

Breaking changes

  • dialects patterns in jsonvet.toml or [tool.jsonvet] match paths relative to that file, not to the working directory.
  • An unknown option such as --x or -x exits 2 instead of 1, unless a file of that name exists.
  • Non-ASCII keys in paths print as written, $["日本"] and not $["\u65e5\u672c"].
  • Rust library: Rule::ALL and Dialect::ALL are slices, Severity and Location are #[non_exhaustive], and UnknownRule and UnknownDialect hide their text behind id() and name().

The full list, with the fixes, is in the changelog.

Install

uvx jsonvet, pip install jsonvet or cargo install jsonvet-cli. The Rust library is the jsonvet crate.

v2.0.0: check-json5 is now jsonvet, rewritten in Rust

Choose a tag to compare

@simonvanlierde simonvanlierde released this 13 Oct 22:34
118b80e

check-json5 is now jsonvet, rewritten in Rust. It gives the same pass or fail as 1.4.1 on every file: I ran both on 20,114 files in JSON5 and strict mode, 40,228 runs, and they agree on all of them.

Upgrade

Set rev: v2.0.0 in .pre-commit-config.yaml. The check-json5 hook id, the check-json5 command and --strict keep working until 3.0, and the old repository URL redirects. To use the new options, switch to the jsonvet hook id.

What's new

  • Six dialects on one parser: JSON, I-JSON, JSONC, JWCC (HuJSON), JSON5 and JSON Lines, picked by file extension or with --dialect.
  • Rules with severities: duplicate-key, invalid-number, byte-order-mark and more, changed with --error, --warn, --ignore and --max-warnings.
  • A config file: jsonvet.toml, or [tool.jsonvet] in pyproject.toml.
  • Faster, with no Python start-up: the hook installs a prebuilt binary. It is 3x faster on 1,100 small config files and 1,398x faster on a 1.8 MB JSON5 file.

Breaking changes

  • Each output line gains its severity and rule, as in file:4:5: error[duplicate-key] duplicate key $.a (first at 2:5), and syntax errors use new wording.
  • Lines end at every JSON5 line terminator, so positions after a lone CR, U+2028 or U+2029 differ from 1.x.
  • The importable Python module is gone. The wheel brings the jsonvet and check-json5 commands.

The full list is in the changelog.

Install

uvx jsonvet, pip install jsonvet or cargo install jsonvet-cli. The Rust library is the jsonvet crate.

v1.4.1

Choose a tag to compare

@simonvanlierde simonvanlierde released this 13 Oct 08:39
b181775

Upgrade: set rev: v1.4.1. Nothing else is needed.

Fixed

  • --strict passed a file where NaN or Infinity runs on into other text, such as [NaN-2.5e3 or Infinitynul }. Those files now fail, with the constant's position.
  • An unquoted JSON5 key written with a \u escape, such as a, was compared with its escape still in place, so it did not match a or 'a', and its path showed the escape. Keys now compare by their decoded name.

v1.4.0

Choose a tag to compare

@simonvanlierde simonvanlierde released this 13 Oct 04:42
138d38a

Upgrade: set rev: v1.4.0. Nothing else is needed.

Added

  • The hook also runs on Tailscale's .hujson and .jwcc, VS Code's .code-workspace and
    .code-snippets, .webmanifest and .babelrc files: all JSON, some with comments.

Changed

  • The hook checks JSON with only comments and trailing commas, such as tsconfig.json, with the
    C-speed json parser instead of json5. Whole hook runs are 11× faster on a 50 KB file and
    56× faster on a 2 MB one. Files that use more of JSON5 still go through json5.
  • A number may have up to 1,000,000 digits. 1.3.0 lifted Python's limit of 4300 altogether,
    which let one file with a huge number stall a run. A longer number now fails its file with a
    message.

Fixed

  • A JSON5 file with comments and an unescaped U+2028 or U+2029 inside a string now passes, as
    the JSON5 spec allows. The json5 package rejected it; strict JSON files already passed.
  • A file with a duplicate key and an undecodable string after it crashed the run with a
    traceback and left the remaining files unchecked. It now reports the duplicate.
  • A newline in a file name is printed as \n, so a file name can no longer inject a GitHub
    Actions workflow command into CI output.
  • Checking a file with many duplicate keys took time that grew with the square of their
    number. 200,000 duplicates took 42 s; they now take under a second.
  • --strict patterns match ./sub/a.json like sub/a.json.

v1.3.0

Choose a tag to compare

@simonvanlierde simonvanlierde released this 13 Oct 00:59
f1251df

Upgrade: set rev: v1.3.0. Nothing else is needed for the hook. Only a script that parses the
hook's output, or imports pre_commit_hooks.check_json5, needs a change (see Changed).

Added

  • Every failure prints as file:line:col: message, so editors and terminals link to it.
  • A duplicate key reports its JSON path ($.server.port), and every repeated key in a file is
    listed, not only the first.
  • On GitHub Actions, each failure is also an annotation on the pull request diff.
  • --strict GLOB holds matching files to strict JSON: no comments, trailing commas or NaN.
    Repeat it to add patterns, and !GLOB exempts files.
  • Published on PyPI, so uvx check-json5 FILE... works without pre-commit.

Changed

  • The output format: f.json: Failed to json decode (<string>:4 Unexpected "," at column 8) is
    now f.json:4:8: Unexpected ",".
  • The module moved from pre_commit_hooks.check_json5 to check_json5.check_json5, so the PyPI
    package no longer collides with pre-commit-hooks. The check-json5 command is unchanged.
  • Tested on Python 3.15.

Fixed

  • A file nested deeper than Python's recursion limit crashed the run and left the remaining files
    unchecked. It now fails on its own.
  • Valid JSON with an integer of more than 4300 digits failed.

v1.2.0

Choose a tag to compare

@simonvanlierde simonvanlierde released this 06 Jul 20:01
c70883b

Highlights

  • Faster validation: new fast json parse path, falling back to json5/jsonc only when needed.
  • .jsonc / .json5 support: the hook now covers comment-bearing JSON variants (plus .geojson/.jsonld).

Also in this release

  • Add CI workflow
  • Add test suite
  • Update dependencies, ruff config, and uv lockfile
  • README: performance notes and badges

Full Changelog: v1.1.0...v1.2.0