json5
A pure Python implementation of the JSON5 data format, mirroring the stdlib json API for near drop-in adoption.
Repository Health
Technical Analysis
json5 (import name json5, distributed as pyjson5 on GitHub) implements a reader and writer for the JSON5 data format in pure Python. JSON5 extends standard JSON with JavaScript-style comments, unquoted object keys, trailing commas, and single-quoted or multi-line string literals, making it a more forgiving format for hand-written configuration files while still round-tripping cleanly to and from ordinary JSON.
The library deliberately mirrors the Python standard library’s json module: load(), loads(), dump(), and dumps() accept the same core signature, so most code written against json can switch to json5 with minimal changes. It adds JSON5-specific extras such as an allow_duplicate_keys flag for loads() and a QuoteStyle enum (ALWAYS_DOUBLE, ALWAYS_SINGLE, PREFER_DOUBLE, PREFER_SINGLE) that controls how output strings are quoted when encoding. A pyjson5 command-line tool is also installed, letting you convert between JSON5 and JSON from the shell.
The project is explicit that it prioritizes spec correctness over raw throughput: the README states plainly that the pure-Python parser can be 1000-6000x slower than the C-accelerated json module, and 200x+ slower than the pure-Python json implementation. It’s best suited to config-file parsing and other low-volume, human-edited-input use cases rather than high-throughput data interchange.
What You Get
- Drop-in-style
load(),loads(),dump(), anddumps()functions matching the stdlibjsonmodule’s signatures - Full JSON5 grammar support: comments, unquoted identifier keys, trailing commas, single-quoted and multi-line strings
- An
allow_duplicate_keysoption onloads()/load()to reject documents with repeated object keys - A
QuoteStyleenum (ALWAYS_DOUBLE,ALWAYS_SINGLE,PREFER_DOUBLE,PREFER_SINGLE) for controlling output string quoting during encoding - A
pyjson5command-line tool for converting between JSON5 and JSON files - Zero runtime dependencies and a
py.typedmarker for static-typing consumers
Common Use Cases
- Parsing hand-written JSON5 configuration files (e.g. build tool or app configs) that use comments or trailing commas
- Accepting more forgiving, human-editable JSON5 input from users while still producing standard JSON output
- Converting JSON5 config files to strict JSON via the
pyjson5CLI as a build or CI step - Round-tripping data with controllable output string quoting for consistency with existing style conventions
Under The Hood
Architecture
The package is a thin, monolithic library layered directly on a generated parser: json5/__init__.py re-exports the public API from lib.py, which implements load/loads/dump/dumps plus the encoding logic, while all actual JSON5 grammar parsing is delegated to json5/parser.py — a recursive-descent parser generated by the author’s separate glop PEG-parser-generator tool from the grammar file json5/json5.g. json5/tool.py implements the pyjson5 CLI by calling the same load/dump functions against file/stream I/O abstracted through json5/host.py. There’s no dependency injection or plugin architecture; data flows in one direction from raw text into Parser(msg, fname).parse(), producing native Python objects that lib.py’s encoding functions can walk back into text. Because lib.py and tool.py both call into Parser directly, any change to the generated parser’s interface would require regenerating and touching both call sites.
Tech Stack
Pure Python 3.8+ with no runtime dependencies. Packaging uses setuptools>=61 via pyproject.toml with a dynamic version pulled from json5/version.py. Development tooling is managed through uv (checked-in uv.lock, a dev dependency group), including ruff for formatting and linting (single-quote style, 79-character line length), mypy for type checking, pylint, coverage, and twine for publishing — all wrapped behind a custom ./run shell script. CI runs on GitHub Actions, testing a matrix spanning Python 3.8 through 3.14 via python run tests.
Code Quality
Tests live under tests/ (lib_test.py, tool_test.py, host_test.py) using the standard library’s unittest framework rather than pytest, with extensive assertEqual-based coverage of the JSON5 grammar surface — arrays, objects, comments, quote styles, duplicate-key handling, and parser error cases. Error handling is explicit: malformed input raises ValueError with a parser-generated message that includes line and column information rather than failing silently. The package ships a py.typed marker and is checked with mypy, and ruff/pylint enforce consistent snake_case naming and formatting. No signs of swallowed exceptions or bare except blocks in the core encode/decode paths.
API Design
The library’s central design decision is mirroring the stdlib json module’s function signatures as closely as possible, which minimizes the learning curve for anyone who has used json.load/json.loads. It layers on a small number of well-documented JSON5-specific extensions — allow_duplicate_keys and the QuoteStyle enum — rather than inventing a broader bespoke API surface. The README is candid about the library’s main trade-off, stating upfront and repeatedly that it is very slow relative to both the C-accelerated and pure-Python json implementations, which is useful, honest guidance for evaluating fit before adoption rather than discovering the limitation in production.
Used by 3 apps in this directory
GPT Researcher
Productivity · AI Assistants
The pioneering open-source autonomous AI agent that conducts deep, multi-source research and produces citation-backed reports exceeding 2,000 words — faster and more reliably than any human researcher.
Keep
Devops · Automation · Monitoring
The open-source AIOps and alert management platform that unifies 130+ monitoring tools into a single pane of glass with AI-powered correlation, deduplication, and workflow automation.
Skyvern
AI Agents · Automation
Skyvern (YC S2023) automates browser-based workflows by pairing LLMs with computer vision, letting agents click, fill, and extract data on sites they've never seen, without brittle XPath selectors that break on every layout change.