laktak/hjson
PHP library for parsing and generating Hjson (Human JSON). Read relaxed JSON with comments, optional commas, and unquoted keys/strings; stringify back to Hjson. Supports preserving whitespace/comments for round-trip editing. Install via Composer: laktak/hjson.
Installation
composer require laktak/hjson
Add to composer.json if using a monorepo or custom setup.
First Parse
Create a .hjson file (e.g., config/app.hjson):
# App Configuration
app_name: "My App"
debug: true
env: [
"local",
"staging"
]
Parse it in a Laravel service provider or controller:
use HJSON\HJSONParser;
$parser = new HJSONParser();
$config = $parser->parse(file_get_contents(base_path('config/app.hjson')));
First Use Case
Replace JSON config files (e.g., config/app.php) with .hjson equivalents. Leverage comments and relaxed syntax for better readability:
# Database Configuration
database: {
driver: "mysql",
host: "127.0.0.1",
port: 3306,
# Uncomment for production
# username: "prod_user",
# password: "prod_pass"
}
Config Files
config/mail.json) with .hjson:
# Mail Configuration
driver: "smtp"
host: "mail.example.com"
port: 587
encryption: "tls"
# Credentials (use env vars in production)
username: "user@example.com"
password: "secret"
config/app.php:
$mailConfig = (new HJSONParser())->parse(file_get_contents(__DIR__.'/mail.hjson'));
return array_merge(config(), $mailConfig);
API Responses
HJSONStringifier to generate human-readable responses for debugging:
use HJSON\HJSONStringifier;
$stringifier = new HJSONStringifier();
return response($stringifier->stringify($data), 200, ['Content-Type' => 'application/hjson']);
Environment-Specific Configs
.hjson files (e.g., config/local.hjson):
# Local Overrides
debug: true
log_level: "debug"
$baseConfig = require __DIR__.'/app.php';
$envConfig = (new HJSONParser())->parse(file_get_contents(__DIR__.'/local.hjson'));
return array_merge_recursive($baseConfig, $envConfig);
Validation with Comments
# User Validation Rules
rules: {
name: "required|string|max:255",
email: "required|email|unique:users",
# Password rules (commented out for demo)
# password: "required|min:8|confirmed"
}
Service Providers: Register HJSON parsers as singletons in AppServiceProvider:
$this->app->singleton(HJSONParser::class, function () {
return new HJSONParser();
});
Inject via constructor:
public function __construct(private HJSONParser $parser) {}
Artisan Commands: Parse HJSON for CLI tools:
$config = $this->parser->parse(file_get_contents($this->laravel->basePath('config/cli.hjson')));
Testing: Use HJSON for test data with comments:
# Test User Data
users: [
{
id: 1,
name: "John Doe",
# Active status (true/false)
active: true
}
]
Whitespace Sensitivity
keepWsc: false in parse() to strip them:
$parser->parse($text, ['keepWsc' => false]);
$parser = new HJSONParser(['keepWsc' => false]);
String Quotes
key: value), but this can cause issues with:
key: hello world fails if world is a reserved word).Optional Commas
{"a": 1,}) are allowed but may cause issues with:
json_encode() if interoperability is needed:
$hjsonData = $parser->parse($text);
json_encode($hjsonData); // Throws error if invalid
File Encoding
.editorconfig to enforce UTF-8:
root = true
[*]
charset = utf-8
Nested Comments
/* */ and # comments, but nested /* */ comments are not allowed:
/* Outer comment
/* Inner comment */ // ERROR
*/
Parse Errors
try-catch to handle malformed HJSON:
try {
$data = $parser->parse($text);
} catch (\HJSON\HJSONException $e) {
Log::error("HJSON Parse Error: " . $e->getMessage());
throw new \RuntimeException("Invalid config file", 0, $e);
}
Stringify Issues
HJSONStringifier may not preserve all HJSON features (e.g., comments). Use json_encode() for strict JSON output:
$json = json_encode($data, JSON_PRETTY_PRINT);
Custom Parsing Options
HJSONParser to add custom options (e.g., trimTrailingCommas):
class CustomHJSONParser extends HJSONParser {
public function parse($text, array $options = []) {
$options['trimTrailingCommas'] = true;
return parent::parse($text, $options);
}
}
File Watching
$config = $this->parser->parse(file_get_contents($path));
Cache::remember("hjson_{$path}", now()->addHours(1), fn() => $config);
IDE Support
.hjson to your IDE’s JSON language support (e.g., VSCode) for syntax highlighting.Validation
Validator for HJSON-based rules:
$rules = (new HJSONParser())->parse(file_get_contents(__DIR__.'/rules.hjson'));
$validator = Validator::make($request->all(), $rules);
keepWsc: true. Explicitly set options to avoid surprises:
$parser = new HJSONParser(['keepWsc' => false]);
? in HJSON becomes null in PHP. Handle null checks explicitly:
if (is_null($config['optional_key'])) {
// Handle missing value
}
How can I help you explore Laravel packages today?