<?php
/**
* 解析带注释的JSONC内容
*
* @param string $json JSON或JSONC格式的字符串
* @param boolean $assoc 是否返回关联数组
* @return mixed 返回解析后的数据或null(如果发生错误)
* @throws Exception 如果JSONC解码失败
* @license WTFPL
*/
function jsonc_decode(string $json, bool $assoc = false) {
// 移除多行注释
$json = preg_replace('/\/\*.+?\*\//s', '', $json);
// 移除单行注释
$json = preg_replace('/\/\/.*/', '', $json);
// 替换掉由于注释移除后可能产生的多余逗号或空格
$json = preg_replace('/[,{]\s*[\r\n]+\s*/', ',', $json);
$json = trim($json);
// 提前检查是否存在未闭合的字符串引号
if (preg_match('/"[^"\\\\\n\r]*(?:\\\\.[^"\\\\\n\r]*)*($|[^"])/', $json, $matches)) {
$start_pos = strpos($json, $matches[0]);
if ($start_pos !== false) {
trigger_error("Unclosed string starting at position: " . $start_pos, E_USER_WARNING);
return null;
}
}
// 转换
$result = json_decode($json, $assoc);
if (json_last_error() !== JSON_ERROR_NONE) {
// 不保证移除注释的效果,但如果解码失败,则抛出异常;我们最好用JSON,但当然我也理解你为什么要用JSONC
throw new Exception('JSONC decoding failed: ' . json_last_error_msg());
}
return $result;
}
?>