-
Notifications
You must be signed in to change notification settings - Fork 42
0.导言
配置文件是一种非常基础的文件格式,但远没有数据文件格式(如 SQLite)、文档文件格式(如 Markdown)、编程语言(如 JavaScript)、甚至二进制文件格式(如 PNG)需求那么复杂。
只要严谨但不严苛、支持必要的数据类型和嵌套,又易于人类手工直接阅读和编辑就可以了。
但就是这样一种广泛需要而又简单的应用场景,却反而长期以来一直没有一种足够好的文件格式。
INI(.ini
)文件是一种非常原始的基础形式,但各家有各家的用法,而且它最多只能解决一层嵌套。只适合非常非常简单的配置文件,一旦需要两层嵌套,或需要数组,就力不从心了。
; 最简单的结构
val_1 = val_1;
val_2 = val_2; 这些等号后面的值是字符串(句末分号不是必须的;它后面的都是注释)
; 稍微复杂一点的单层嵌套结构
[obj_1]
x = obj_1.x
y = obj_2.y
[obj_2]
x = obj_2.x
y = obj_2.y
JSON(.json
)是一种非常好的数据存放和传输的格式,但阅读和编辑它实在不方便。即便 JSON5(.json5
- ECMAScript 5.1 JSON)这种扩展格式允许了你像写 JavaScript 对象那样书写裸键名、允许尾逗号,并且可以有注释,写多行字符串依然麻烦。即便它将来加上了多行字符串语法,依然不行,因为它虽然是基于括号嵌套语法的层级关系,在不缩进的情况下,却根本没法阅读。
{
"val_1": "val_1"
,
"val_2": "val_2"
,
"obj_1": {
"x": "obj_1.x"
,
"y": "obj_1.y"
}
,
"obj_2": {
"x": "obj_2.x"
,
"y": "obj_2.y"
}
,
"arr": [
{ "x":"arr[0].x", "y":"arr[0].y" }
,
{ "x":"arr[1].x", "y":"arr[1].y" }
]
}
YAML(.yaml
或 .yml
)干脆将 JSON 中有了不够、没有不行的括号结构去掉了,只保留缩进。但编辑和阅读它总令人非常慌张,生怕数错了层次(实际上,对于阅读,语法关键字并不是越小越好)。而且在不支持统一缩进、反缩进、自动在换行时缩进的编辑环境下,这非常麻烦——这本来对编程语言来说不是什么事,但配置文件最常用的使用场景却恰恰是这样。
另外,YAML 的语法实在太多了,而且不是循序渐进的,即便你不需要复杂的功能,为了保证自己的简单功能不出错,也要对那些复杂的语法有所了解并加以避免(比如究竟什么键名可以不加引号,什么字符串可以不加引号;你总不能为了避免歧义全都加上引号,那和 JSON 也就差球不多了)。更糟的是,纵使如此复杂,想要精确地配置一段多行字符串,却显得力不从心——除非倒退回单行 JSON 字符串表示法,否则其中的换行是否被保留、缩进是否被忽略、是否自动插入了空格、转义的解释等问题,实在令人心力交瘁。再加上各种实现对各种歧义的解释异常混乱……要说规范一点儿责任也没有,似乎是不可能的。
val_1: abcd # string
val_2: true # boolean
val_3: TRUE # ?
val_4: True # ?
val_5: TrUE # ?
val_6: yes # ?
val_7: on # ?
val_8: y # ?
obj_1:
x: obj_1.x
y: obj_1.y
obj_2:
x: obj_2.x
y: obj_2.y
arr:
- x: arr[0].x
y: arr[0].y
- x: arr[1].x
y: arr[1].y
str_1: "a
b" # ?
str_2: "a
b" # ?
str_3: "a
b" # ?
终于,TOML(.toml
)横空出世。它彻底放弃了括号或缩进的底层原理,而是采取了显式键名链的方式。
为了方便(同时看起来更清楚——这种读和写的契合非常关键!),你可以指定小节名。妙的是,小节名也是可以链式声明的。
另外,某些数据可能使用内联数组或表更合适以避免臃肿,这也是支持的。
val_1 = "val_1"
val_2 = "val_2"
obj_1.x = "obj_1.x"
obj_1.y = "obj_1.y"
[obj_2]
x = "obj_2.x"
y = "obj_2.y"
[[arr]]
x = "arr[0].x"
y = "arr[0].y"
[[arr]]
x = "arr[1].x"
y = "arr[1].y"
[str.x]
y.z = "str.x.y.z"
[str.a]
b.c = """
str
.a
.b
.c
""" # 等价于 " str\n .a\n .b\n .c\n"
[inline]
points = [
{ x=1, y=1, z=0 },
{ x=2, y=4, z=0 },
{ x=3, y=9, z=0 },
]
现在就开始你的 TOML 之旅吧!
© 2022 龙腾道