JSON 配置文件的缺点

原文链接:The downsides of JSON for config files

我近期目睹了使用 JSON 作为配置文件的趋势,我认为这不是一个好主意。

这不是 JSON 的设计目的,因此它不擅长做这件事。JSON 旨在成为一种“轻量数据交换格式”,并声称其“易于人类读写”和“易于机器解析和生成”。

作为一种数据交换格式,JSON 相当不错。人类可以相对容易地读写它,而且机器解析起来也很容易(尽管存在一些问题)。

这是一个良好的在机器可读和人类可读之间的权衡,对于许多用例来说,这是对 XML 的一个很好的改进。

将其用于其它目的有些类似于:“嘿,这把锤子非常适合用来钉钉子!我很中意它!为什么不用它来敲这颗螺丝呢!”。当然,这么做也可以,但它不是正确的工具。


截止到目前,最大的问题是你无法添加注释。少数 JSON 解析器可以,但大多数都不支持,它也不在标准中。有充分的理由关于明确从 JSON 中移除注释。

你想要添加注释的原因有很多:记录为什么设置成该值,添加助记符或描述警告,警告过去的配置错误,在其中保留一个基本的更改日志,或者单纯是为了在调试时注释掉某个段落或值。

一个变通方法是添加一个新的键(如 {"__comment": "a comment", "actual_data": "..."},但我觉得这实在是太难看了)。

你也可以使用提交日志,但是谁会在提交历史中不大可能隐藏一些重要信息的情况下去仔细阅读它呢?

一些 JSON 方言例如 JSON5,Hjson 和 HOCON 添加了对注释的支持,一些 JSON 解析器也是如此。这很好,我也鼓励你去使用它,但这不再是 JSON 了,而是 JSON 方言。这篇文章是关于 JSON 的,不是它的方言。


我还发现在手动编辑 JSON 时的体验很不理想,你需要频繁的追加逗号,引号的语义非常烦人,而且它缺乏使用多行字符串的能力。这些属性适用于 JSON 的预期用途,但不太适合编写配置文件。它可行吗?当然。有趣吗?不。

我也没觉得它特别易读,因为它包含过多的引号和其它语法噪音。我坦率承认这可能是我的品位问题。


JSON 是一种声明性配置语言。声明性配置(DC)适用于某些问题,但其它问题就不那么适用了。尤其是使用 DC 来控制逻辑,通常不是个好主意。

促使我写这篇文章的是 MediaWiki 的新扩展系统,旧系统使用一个简单的 PHP 文件来连接核心 MediaWiki 代码,加载所需依赖等。这些在新系统中被一个 JSON 文件替换。丧失了巧妙解决与其它插件或逻辑的兼容问题的能力。

它实现起来也很复杂,以前只需要 require('plugin/foo/plugin.php');,现在它需要解析一个 JSON 文件,并根据其内容做些什么。这要复杂得多,因此也难以测试

而使用 JSON 文件存储基本的元数据是有意义的(更容易在网站上解析和显示),用它来描述代码的工作方式对于我来说是对 DC 的滥用。毕竟这是代码的活儿。


很多人向我征求关于使用什么的建议。这不是个容易回答的问题,因为它取决于你的用例,编程语言,库环境和社会因素。没有单一的“正确答案”,也许只有“最简单的,满足你所有需求”的答案。事实上我写了一篇关于这一点的文章

一个很好的选项可能是只使用命令行标志

有一些 JSON 方言专为人类编写而设计:JSON5HjsonHOCON。所有这些似乎都是对标准 JSON 的合理改进,尽管我没有用过它们中的任何一个。特别是 JSON5 似乎是个不错的选项,因为它对 JSON 的改动最少。

我不愿提供其它选项,因为我没有对所有格式( YAML 除外)进行深入评估;只是看看规范可能无法找出潜在的缺点( YAML 就是个很好的例子,它有很多微妙的行为)。我确实没有时间或是兴趣去对所有选项做全面深入的审查。