jsonclark - JSON Comments parsed with Lark
This library parses JSON files that contain C-style comments (// and /* */),
which is useful commonly used in configuration files and other applications
where comments enhance readability. Notable cases are VSCode and Zed editor.
✨ Features
- Parses JSON with both single-line (
//) and multi-line (/* */) comments. - Extract and preserve comments while parsing
- Full JSON compatibility (objects, arrays, strings, numbers, booleans, null)
- Built with Lark for reliable parsing
- Comprehensive test coverage
- CLI tool with support for yq expressions to modify JSON while preserving comments
⚠️ Disclaimer
AI-Generated Code: A significant portion of this codebase has been generated using AI code assistants (such as GitHub Copilot). While the code has been reviewed and tested, please be aware that parts of the implementation may have been initially generated by AI models. All functionality has been validated through comprehensive test coverage.
📦 Installation
pip install jsonclark
Or with development dependencies:
pip install "jsonclark[dev]"
Or run directly from git using uvx:
uvx --from git+https://github.com/D3f0/jsonclark@main jsonclark --help
🛠️ Command-Line Tool
After installing jsonclark, you can use the jsonclark command to pretty-print JSON files with support for comments, similar to Python's json.tool:
Usage
# Pretty-print JSON from stdin
cat config.jsonc | jsonclark
# Pretty-print with custom indentation
cat config.jsonc | jsonclark --indent 4
# Sort keys in output
cat config.jsonc | jsonclark --sort-keys
# Show extracted comments
cat config.jsonc | jsonclark --comments
# Pretty-print from file
jsonclark config.jsonc
# Apply yq expression to modify JSON (preserves comments for file input)
jsonclark --yq '.port = 9000' config.jsonc
# All options together
jsonclark --indent 4 --sort-keys --comments config.jsonc
Options
--indent INDENT: Number of spaces for indentation (default: 2)--sort-keys: Sort dictionary keys in output--comments: Show extracted comments in the output--yq EXPRESSION: Apply a yq expression to modify the JSON. When used with file input, automatically creates a backup (file.bak) before modification.--version: Show program version--help: Show help message
🔧 Using yq for JSON Modification
The --yq flag allows you to apply yq expressions to modify your JSON while preserving comments (when operating on files). This is useful for CI/CD pipelines and configuration management.
📋 Requirements
The yq binary must be installed. Install it with:
On macOS:
brew install yq
From GitHub releases: Visit https://github.com/mikefarah/yq/releases
Using pip:
pip install yq
📝 Examples
# Modify a single key
jsonclark --yq '.port = 9000' config.jsonc
# Add a new key
jsonclark --yq '.debug = true' config.jsonc
# Delete a key
jsonclark --yq 'del(.deprecated_field)' config.jsonc
# Modify nested values
jsonclark --yq '.server.host = "0.0.0.0"' config.jsonc
# Work with stdin (output to stdout)
cat config.jsonc | jsonclark --yq '.version = "2.0"'
💾 Backup on File Modification
When --yq is used with file input, jsonclark automatically creates a backup file:
jsonclark --yq '.port = 9000' config.jsonc
# Creates: config.jsonc.bak (contains the original)
# Updates: config.jsonc (contains the modified version)
If yq is not installed, you'll see an error message with installation instructions.
🚀 Quick Start
Basic Usage
Parse JSON with comments using the load_json_with_comments() function:
from jsonclark import load_json_with_comments
json_text = """
{
// User configuration
"name": "John Doe",
// Age in years
"age": 30
}
"""
config = load_json_with_comments(json_text)
print(config) # {'name': 'John Doe', 'age': 30}
Preserving Comments
If you want to extract comments separately, use load_json_preserving_comments():
from jsonclark import load_json_preserving_comments
json_text = """
// Configuration file
{
// Database settings
"database": "postgres"
}
"""
result = load_json_preserving_comments(json_text)
print(result["value"]) # {'database': 'postgres'}
print(result["comments"]) # ['Configuration file', 'Database settings']
💬 Comment Types
Line Comments
Use // for single-line comments:
{
// This is a line comment
"key": "value"
}
Block Comments
Use /* */ for multi-line comments:
{
/*
* This is a block comment
* spanning multiple lines
*/
"key": "value"
}
Mixed Comments
You can mix both types:
{
// Line comment
"setting1": "value1",
/* Block comment */
"setting2": "value2"
}
🔥 Advanced Usage
Using the Parser Class Directly
For more control, use the JSONWithCommentsParser class:
from jsonclark import JSONWithCommentsParser
parser = JSONWithCommentsParser()
# Parse and get result
result = parser.parse('// Comment\n{"key": "value"}')
# Parse and preserve comments
result = parser.parse_with_comments('// Comment\n{"key": "value"}')
print(result["value"]) # {'key': 'value'}
print(result["comments"]) # ['Comment']
Extracting Comments Only
If you only need to extract comments from JSON:
from jsonclark import JSONWithCommentsParser
text = '// Comment 1\n/* Comment 2 */\n{}'
comments = JSONWithCommentsParser._extract_comments(text)
print(comments) # ['Comment 1', 'Comment 2']
🌍 Real-World Example
Here's a configuration file example:
from jsonclark import load_json_with_comments
config_text = """
{
// Server configuration
"server": {
"host": "0.0.0.0",
// HTTP port
"port": 8080,
/* SSL settings */
"ssl": {
"enabled": true,
"certificate": "/etc/ssl/cert.pem"
}
},
// Database connection
"database": {
"type": "postgresql",
"host": "localhost",
/* Connection pool size */
"poolSize": 20
}
}
"""
config = load_json_with_comments(config_text)
print(f"Server: {config['server']['host']}:{config['server']['port']}")
print(f"Database: {config['database']['type']}")
print(f"Pool Size: {config['database']['poolSize']}")
📊 Data Structures
JSONValue
Optional dataclass for representing JSON values with comment metadata:
from jsonclark import JSONValue
value = JSONValue(
value={"key": "value"},
comments_before=["Opening comment"],
comments_after=["Closing comment"]
)
📚 API Reference
Functions
-
load_json_with_comments(text: str) -> Any- Parse JSON with comments and return the parsed Python object
- Raises
lark.exceptions.LarkErrorfor invalid JSON
-
load_json_preserving_comments(text: str) -> dict[str, Any]- Parse JSON and return both value and comments
- Returns
{"value": parsed_object, "comments": [list_of_comments]}
Classes
JSONWithCommentsParser- Main parser class
- Methods:
parse(text: str) -> Any- Parse JSON and return Python objectparse_with_comments(text: str) -> dict[str, Any]- Parse and preserve comments_extract_comments(text: str) -> list[str]- Static method to extract comments
✅ Testing
With Nox (Multi-version Testing)
Test across Python 3.10 - 3.13 using nox:
# Install nox with uv support
pip install nox-uv
# Run tests on all Python versions
nox
# Test specific version
nox -s tests-3.13
# Run only parser tests
nox -s tests_parser-3.13
# Run only CLI tests
nox -s tests_cli-3.13
With Pytest
Run the comprehensive test suite:
pytest tests/ -v
All tests pass ✅
⚡ Limitations
- Comments must follow C-style syntax (
//and/* */) - Comments inside strings are preserved as part of the string value
- The parser focuses on standard JSON data types (no trailing commas or unquoted keys)
📋 Requirements
- Python >= 3.10
- Lark >= 1.3.1
📄 License
MIT
🤝 Contributing
Contributions are welcome! Please ensure all tests pass before submitting a pull request.
pytest tests/test_parser.py
Metadata
Release files for jsonclark 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| jsonclark-0.2.2.tar.gz | 14.4 kB | Without provenance | Details for jsonclark-0.2.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| jsonclark-0.2.2-py3-none-any.whl | Python 3 | none | any | Details for jsonclark-0.2.2-py3-none-any.whl |
Total release size: 25.8 kB
Release files / jsonclark-0.2.2.tar.gz
| Download URL | jsonclark-0.2.2.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e9540b6a458c68eee093520afbf8de5ca69278e1c956fd687123e7a077eba066
|
|
BLAKE2b-256 checksum How to use checksums |
885178d67e465f441806fa3041d61f576519fe3182f5b26f92e1b8e7bde94101
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / jsonclark-0.2.2-py3-none-any.whl
| Download URL | jsonclark-0.2.2-py3-none-any.whl |
|---|---|
| Size | 11.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6d36a717ba8396a0c4620896cebbca7db5bb18b585141a83a20eaefd5f1555ed
|
|
BLAKE2b-256 checksum How to use checksums |
0fb389e6996b412d1ba5f9d386b100e7fd3b73df4cd96c01f3a33b80398f6c97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for jsonclark 0.2.2
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.