任何人都可以建议一个JSON解析器允许任何类型的注释,使用PHP绑定 - 需要对配置文件的评论,但json_decode不支持它们。
(我知道:1。其他格式如YAML,2。评论不是标准的一部分)
更新
我们为什么不使用:
YAML:基准显示速度较慢 - 我们可能希望通过网络发送数据 - 不确定YAML是否最适合。
XML:太冗长 - 简单的人工编辑是必需的。并且不需要XML的扩展功能。
INI:数据中存在可变深度的层次结构和嵌套。我们需要一种无处不在的格式,因为数据可能会与应用程序一起分发,也可能与其他语言的应用程序一起使用。
预处理:数据可以由用户提供和共享,在向应用添加数据之前很难强制要求进行预处理。
答案 0 :(得分:8)
如果您需要可移植性并且不希望任何预处理来修复非标准组件,那么YAML可能就是您的选择。
大多数(如果不是全部)JSON与YAML兼容(YAML是JSON的超集),它支持注释。
对于最近的一个项目,我觉得有必要从.ini
转移到我们的“默认设置”文件 - 这样我们就不再需要将一些字符串转换为整数或布尔值(从parse_ini_file
开始将值解析为字符串,foo=1
或foo=true
都是字符串值。)
JSON似乎是一种很好的格式,但它不支持评论。但是,如果你想让这个工作,我建议不要完全实现(或使用)一个单独的JSON解析器。我所做的是创建一个简单的包装函数,用正则表达式去掉注释,然后使用原生的json_decode
。
来自https://github.com/countervandalism/stillalive/blob/v2018.11/src/Util.php#L21-L41的示例:
class Util {
/**
* From https://stackoverflow.com/a/10252511/319266
* @return bool|array
* @throws ParseException
*/
public static function loadConfig( $filename ) {
$contents = @file_get_contents( $filename );
if ( $contents === false ) {
return false;
}
return json_decode( self::stripComments( $contents ), true );
}
/**
* From https://stackoverflow.com/a/19136663/319266
* @param string $str
*/
public static function stripComments( $str = '' ) {
$str = preg_replace( '![ \t]*//.*[ \t]*[\r\n]!', '', $str );
return $str;
}
答案 1 :(得分:3)
您可以使用以下函数解码已注释的json:
function json_decode_commented($json, $assoc = false, $maxDepth = 512, $opts = 0) {
$data = preg_replace('~
(" (?:[^"\\\\] | \\\\\\\\ | \\\\")*+ ") | \# [^\v]*+ | // [^\v]*+ | /\* .*? \*/
~xs', '$1', $data);
return json_decode($json, $assoc, $maxDepth, $opts);
}
它支持所有PHP风格的注释:/ *,#,//。字符串值保持不变。
答案 2 :(得分:2)
注释不是JSON的一部分,因此不需要“JSON解析器”来接受注释。
我会使用YAML。即使解析稍慢(PHP有一个本机JSON解析器但没有本机YAML解析器),它可能是可以忽略的,如果不是,你可以随时缓存解析的对象。除此之外,由于PHP JSON解析器不支持注释,您必须使用非本机注释,即它很可能不会比YAML解析器更快(假设两者都写得很好)
答案 3 :(得分:0)
另一个选择是允许您的用户在JSON结构中将注释作为未使用的字段插入:
{
"color": "red",
"color//": "may be red, green or blue"
}
如果仅使用JSON进行输入,并且从未进行过机器保存,则可以滥用该格式重复使用同一字段,从而在解析时偶然地几乎消除了注释(通常只有第一个或第二个字段的最后一个值将保留在已解析的结构中):
{
"color": "red", "//":"may be red, green or blue",
"shape": "circle", "//":"use circle, square or triangle",
"timeout": 5, "//":"timeout in seconds; default is 10"
}