PHP无法原生读写HJSON文件,因其json_decode/encode不支持注释、尾逗号等HJSON特性;必须通过hjson CLI等外部工具先转为标准JSON再解析,或用纯PHP库(如hjson-php)替代,但需注意兼容性与安全性。

PHP 无法原生读写 HJSON 文件
HJSON 是一种人类可读的 JSON 超集,支持注释、尾逗号、单引号、不加引号的键等特性,但 PHP 的 json_decode() 和 json_encode() 完全不识别这些语法——直接用会报 JSON_ERROR_SYNTAX 错误。你不能绕过解析阶段把它当普通文本处理,否则丢失结构语义(比如嵌套对象、布尔值、null)。
必须先转成标准 JSON 再交给 PHP 处理
核心思路是:用外部工具把 HJSON 转成合法 JSON 字符串,再由 PHP 解析;写入时则反向操作——PHP 生成数组 → 转成 JSON → 用 HJSON 工具美化为 HJSON 格式。
- 推荐使用 Node.js 的
hjsonCLI 工具(npm install -g hjson),稳定且维护活跃 - PHP 中调用需确保系统已安装 Node.js 和
hjson,并注意执行权限与超时设置 - 读取示例:
$hjsonContent = file_get_contents('/path/to/config.hjson'); $json = shell_exec("echo " . escapeshellarg($hjsonContent) . " | hjson -j 2>/dev/null"); $data = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException('HJSON to JSON conversion failed'); } - 写入时不要手动拼接 HJSON 字符串——注释、缩进、引号规则极易出错;应让
hjsonCLI 从 JSON 输入生成:$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE); $hjson = shell_exec("echo " . escapeshellarg($jsonData) . " | hjson -s 2>/dev/null"); file_put_contents('/path/to/config.hjson', $hjson);
注意安全与环境隔离问题
shell_exec() 直接执行命令风险高,尤其当 $hjsonContent 或 $data 来自用户输入时——即使用了 escapeshellarg(),Node.js 进程本身也可能被注入(如通过环境变量或临时文件)。生产环境建议:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 限定
hjson命令路径,避免 PATH 劫持:/usr/local/bin/hjson而非仅hjson - 用
proc_open()替代shell_exec(),可控制 stdin/stdout/stderr 并设超时 - 若无法部署 Node.js,改用纯 PHP 的 HJSON 解析器(如 hjson-php),但要注意它不支持全部 HJSON 特性(例如多行字符串、无引号键的兼容性较弱)
- 开发机和 CI 环境中容易忽略
hjson版本差异——v4 和 v5 对尾逗号的容忍度不同,务必锁定版本
为什么不用正则替换“模拟”HJSON 支持
有人尝试用 preg_replace() 去掉注释、补引号、删尾逗号,再喂给 json_decode()。这种做法在简单配置里可能“凑合能用”,但实际踩坑极多:
立即学习“PHP免费学习笔记(深入)”;
- 正则无法正确处理嵌套结构中的注释(如对象内字符串含
//) - 单引号字符串里含撇号(
O'Reilly)会导致引号补全失败 - 未加引号的键名若含空格或连字符(
api-url),JSON 解析器直接拒绝 - 没有标准语法树,容错率归零——一个格式错误就整块失效
真正省事的方式是接受「HJSON 是前端/配置层格式,PHP 层只负责数据逻辑」这个边界。只要转换链路稳定,就不必强求 PHP 原生支持。


















