otar / jsonc
A production-ready PHP library for parsing JSONC (JSON with Comments) format with drop-in compatibility for json_decode()
Requires
- php: ^8.1
- ext-json: *
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.5 || ^10.0 || ^11.0 || ^12.0
README
A production-ready PHP library for parsing JSONC (JSON with Comments) format with drop-in compatibility for json_decode().
Features
- Single-line comments (
//) and multi-line comments (/* */) - Trailing commas in objects and arrays
- Drop-in replacement for
json_decode()— same signature, same error behavior, verified by a differential test suite - Edge case handling: Preserves strings with comment syntax, escaped characters, Unicode
- Strict by default: malformed input (raw control bytes, unclosed strings or comments) is rejected like native
json_decode()does — never silently sanitized - Fast: plain JSON takes a native
json_decode()fast path; JSONC goes through a single-pass scanner - Zero dependencies: Uses native PHP JSON extension
- Well tested: 150+ tests with 100% code coverage, PHPStan at max level
Installation
composer require otar/jsonc
Usage
Global Function
// Use global function wrapper $data = jsonc_decode($jsonc, true); // Check for errors using native PHP functions if (json_last_error() !== JSON_ERROR_NONE) { echo json_last_error_msg(); }
Basic Usage
use Otar\JSONC; $jsonc = '{ // This is a comment "name": "John Doe", "age": 30, "hobbies": [ "reading", "coding", // Inline comment ], }'; $data = JSONC::decode($jsonc, true); // ['name' => 'John Doe', 'age' => 30, 'hobbies' => ['reading', 'coding']]
Parse to JSON String
use Otar\JSONC; $jsonc = '{/* comment */"key": "value",}'; $json = JSONC::parse($jsonc); // '{ "key": "value"}' — comments become a space, trailing commas are dropped // Now you can use with standard json_decode $data = json_decode($json, true);
API Reference
JSONC::decode()
Decodes a JSONC string. Drop-in replacement for json_decode().
public static function decode( string $jsonc, ?bool $associative = null, int $depth = 512, int $flags = 0 ): mixed
JSONC::parse()
Parses JSONC string and returns cleaned JSON string (without comments and trailing commas).
public static function parse(string $jsonc): string
Throws Otar\JsoncSyntaxException when the input ends inside an unclosed string literal or block comment — it never returns invalid JSON.
jsonc_decode()
Global function alias for JSONC::decode().
Error Handling
decode() follows json_decode() exactly: invalid input returns null and sets the native error state.
$invalidJsonc = '{invalid json}'; $result = JSONC::decode($invalidJsonc); if ($result === null && json_last_error() !== JSON_ERROR_NONE) { echo 'Parse error: ' . json_last_error_msg(); }
With JSON_THROW_ON_ERROR it throws instead. Unclosed JSONC constructs surface as Otar\JsoncSyntaxException — a JsonException subclass that reports where the construct opened:
use Otar\JsoncSyntaxException; try { JSONC::decode('{"a": 1, /* unterminated', flags: JSON_THROW_ON_ERROR); } catch (JsoncSyntaxException $e) { echo $e->getMessage(); // Unclosed block comment starting at offset 9 $e->getOffset(); // 9 } catch (JsonException $e) { // any other JSON syntax error }
JSONC::parse() always throws JsoncSyntaxException for unclosed constructs, with or without flags.
Differences from json_decode()
- A leading UTF-8 BOM is tolerated and stripped (native
json_decode()rejects it) — JSONC config files frequently carry one. - Comments and trailing commas are accepted.
- Everything else matches native behavior, including
json_last_error()codes. json_last_error()is only meaningful afterdecode();parse()may probe the input internally, which writes the global JSON error state.
Requirements
- PHP 8.1 or higher
- JSON extension (enabled by default in PHP)
Testing
# Run tests composer test # Run tests with coverage composer test-coverage # Static analysis (PHPStan, level max) composer phpstan # Micro-benchmark composer bench
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please ensure all tests pass (composer test) and maintain code coverage.
Credits & Related Projects
Inspired by existing JSONC parsers and the need for a robust, production-ready PHP implementation with proper edge case handling.
- microsoft/node-jsonc-parser - Official JSONC parser for Node.js
- VS Code - Uses JSONC for configuration files