Skip to main content

· 8 min read
Junlin Zhou

翻译自这篇文章

我最近接触到许多项目将 JSON 用作配置文件。我认为这不是一个好主意。

JSON 从设计之初就不是用于做配置文件的,这也不是它擅长的领域。JSON 的目标是 "轻量级数据交换格式", 同时具有 "易于人类读写", "易于代码解析和生成" 的特点。它在对 "人类而言的便利性" 和 "对机器而言的便利性" 之间取得了较好的平衡, 在许多应用场景下都是比 XML 更好的替代方案。

然而,将 JSON 用于其他目的有点类似于说 "嘿,这把锤子非常适合钉钉子!我喜欢它!为什么不用它来拧螺丝!" 当然它不是完全不能用,只是不合适做这样的工作。

目前为止,将 JSON 用作其它用途最大的问题在于不能在 JSON 文件中添加注释。某些特定的 JSON 解析器支持在 JSON 中添加注释,但是绝大部分的解析器都不支持。JSON 的发明者 Douglas Crockford 声称 JSON 最开始是支持注释的,然而由于一些原因,他特意移除了对注释的支持。想要深入研究的朋友可以看这里

我们在写配置文件时经常会遇到需要添加注释的场景。例如解释为什么将配置项设置为当前的值,添加一些助记符或是注意事项,对于错误配置的警告,在文件中保存一份基础的 changelog,又或单纯是在debug时需要注释掉一些配置项。

一个可行的解决方法是将原本的数据存储在一个 object 中,在这个 object 中通过两个条目分别存储数据和注释。例如原本的配置文件如下:

{
"config_name": "config_value"
}

修改后变成如下形式:

{
"config_name": {
"actual_data": "config_value",
"comment": "a comment"
}
}

但是在我看来这种方式丑的压批。

还有一些人指出可以通过 commit log 的形式来实现注释 (译者:不清楚他这里指的是不是 git commit log,如果是的话把这个当作注释方式好像十分难用吧?),但是又有几个人会去细读 commit history?

一些基于 JSON 进行扩展的格式,例如 JSON5HjsonHOCON,以及一小部分 JSON 解析器添加了对注释的支持。这很实用,但这些都属于 JSON 的变种,因此不在本篇的讨论范围之内。

同时我也发现手工编辑 JSON 的用户体验不是那么友好:你得留意行尾是否要添加逗号,得了解用不用引号对含义的影响,同时 JSON 也不支持字符串内换行。这些特性对于 "轻量级数据交换格式" 而言不是坏事,但是对于编辑配置文件这件事来说却不是那么可爱。总的来说,将 JSON 用作配置文件虽然可行,但并不优雅。

MediaWiki 的新扩展系统促使我写下这篇文章。旧的系统通过 PHP 文件来挂接核心代码,加载所需的依赖项等。新系统通过 JSON 文件实现这些配置。这样的更新损失了 PHP 那种能够巧妙解决与其他插件兼容性的能力。 (这段没看懂)

同时它也带来了更多实现复杂度。旧的系统在引入配置文件时仅仅需要一行代码:

require('plugin/foo/plugin.php');

而新系统却需要对 JSON 文件的内容进行解析。这在提升实现复杂度的同时,也提高了 debug 的难度。 (这段不太赞同,XML 作为配置文件,同样要进行解析,这不是 JSON 的问题。)

使用 JSON 文件存储基本元数据是可行的(更容易解析以及在网站上显示),但使用它来描述代码的工作方式对我来说是滥用 DC(Declarative configuration ,声明性配置)。毕竟,这是代码的工作。

许多人问我那到底该用什么(来做配置文件),这其实是个很复杂的问题,关系到你程序的应用场景、编程语言、库环境甚至一些社交因素(?)。最好的回答可能就是“找到能符合你需求的最简单的方案”。

有一些 JSON 的扩展格式更适合于人类进行编辑,例如 JSON5、Hjson 和 HOCON。这些看起来都是普通JSON的合理升级,尽管我自己没有使用过它们。特别是 JSON5 似乎是一个不错的选择,因为它对 JSON 的改动最少。我不能给出关于这些扩展格式的建议,因为我没有所有的格式进行深入的比较。只是看一眼格式规范并不能发现潜在的缺点(YAML 就是一个很好的例子)。我没有时间或是兴趣对所有替代方案进行全面深入的审查。

后记

这是我第一次做需要发布到网上的比较正式的翻译工作。虽然最早自己在读 paper 的时候因为英语生疏,也会边读边翻译一些,但是毕竟那是翻译给自己看的,只要自己能看懂就行了,也不用追求什么语句通顺之类的。然而要发布出来的文章不一样,至少要保证大多数读者能够看得懂。

整篇翻完回过头看看,还是有很多生硬似机翻的地方,主要原因可能还是自己的表达能力不够。翻译技术文章在我看来是个吃力不讨好的活,翻的再好也不如直接读原文来的清晰。至于为什么要做这样的事情, 我想有时间单独写一篇谈一谈。目前来看,就权当是对于自己表达能力的锻炼吧。

· One min read
Junlin Zhou

最近开始接触 Linux 运维的工作,第一件事情就是看看系统中跑了多少服务。

集群用的是 CentOS 7,可以通过 bash systemctl list-unit-files 这个命令查看所有服务,敲下回车后打印出来这么一堆玩应儿:

services

service 的 disabledenabled 状态都好理解,static 是个啥?在不存在的网站上一顿查找,找到如下这番解释:

"static" means "enabled because something else wants it". Think by analogy to pacman's package install reasons:

  • enabled :: explicitly installed
  • static :: installed as dependency
  • disabled :: not installed

意思是,状态为 static 的服务,是作为别的服务的依赖而存在。

· One min read
Junlin Zhou

org.springframework.data.annotation.Id

org.springframework.data.annotation.Id 是 Spring 定义的 annotation,用来支持 "没有像 JPA 那样的持久化 API" 的非关系型数据库或是框架的持久化,因此它常被用于其它 spring-data 项目,例如 spring-data-mongodb 和 spring-data-solr 等。

javax.persistence.Id

javax.persistence.Id 是由 JPA 定义的 annotation,JPA 仅适用于关系数据的管理。

Ref

· One min read
Junlin Zhou

If you installed Postgres from homebrew, the default user postgres isn't automatically created, you need to run following command in your terminal:

/Applications/Postgres.app/Contents/Versions/9.*/bin/createuser -s postgres

· One min read
Junlin Zhou

通过 ubuntucentos 的源安装的 vim 版本较老(好像是7.4.x)

8.0 之后的 vim,官网推荐的安装方式是从 git clone 源码编译

默认编译出来的 vim 是没有 clipboard support 的,无法通过寄存器与系统剪切板进行交互

在编译时增加 clip board support 需要的最小依赖为 xorg header filesx11 dbus

https://packages.ubuntu.com 里一通搜索发现 xorg header files 是在 libx11-dev 这个包里,而 x11 dbusdbus-x11

因此整个编译过程如下:

sudo apt-get install libx11-dev dbus-x11
./configure --with-features=huge
make
sudo make install