Skip to content

otar/jsonc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

otar/jsonc

A production-ready PHP library for parsing JSONC (JSON with Comments) format with drop-in compatibility for json_decode().

CI codecov PHP Version License

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 after decode(); 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.

About

JSONC parser for PHP

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages