TOML是什么?TOML:Tom’s Obvious, Minimal Language。简单来说就是Github的一位创始人觉得YAML太复杂了,所以设计了一款简单的标记语言。 那么YAML又是嘛?YAML: YAML Ain’t Makrup Language。又是玩骇客那一套递归缩写,类似GNU :GNU’s Not Unix! 这里说的“Markup Language”其实也不神秘,程序猿都知道XML、HTML就是这类语言。而标记语言YAML一般使用在配置文件、文本书写(类比Markdown,Sphinx就是用的YAML来写内容)。作者Tom就是觉得YAML太过复杂(Spec 84页),因此定义了这个新的标记语言。而他最常用的地方也就是在配置文件中,可以和INI文件做对比。

如果你用过JSON做配置文件,那肯定会遇到过一个问题就是各种大小括号和结尾的逗号,一旦不小心就会导致解析失败。再设想有强迫症的你,要是JSON配置文件被人改的格式不统一,或者不同编辑器(Linux/Windows)导致的换行问题是又多揪心。而TOML则更清晰简单,容易理解,格式整洁,不易出错。

来看个例子

这个例子引自官方的v0.4.0的Spec

# This is a TOML document. Boom.

title = "TOML Example"

[owner]
name = "Lance Uppercut"
dob = 1979-05-27T07:32:00-08:00 # First class dates? Why not?

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

[servers]

  # You can indent as you please. Tabs or spaces. TOML don't care.
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

[clients]
data = [ ["gamma", "delta"], [1, 2] ]

# Line breaks are OK when inside arrays
hosts = [
  "alpha",
  "omega"
]

相比较JSON是不是简单的多。

基本语法解析

注释

和Shell一样采用"#“做单行注释,没有JSON礼貌的”/**/“多行注释

# I am a comment. Hear me roar. Roar.
key = "value" # Yeah, you can do this.

字符串

TOML中的字符串只能包含UTF-8字符,有四种表达方式:基本字符串、多行基本字符串、字面字符串(Literal String)、多行字面字符串。

  1. 基本字符串:使用双引号括起来一段字符串内容,如果内容中有双引号什么的需要使用反斜杠进行转义,这个就和一般编程语言中的字符串一样。

    “I’m a string. "You can quote me". Name\tJos\u00E9\nLocation\tSF.”

这里的“\t”、“\u00E9”就是一般的UTF-8表示。

  1. 多行基本字符串:跟Python一样,使用三个双引号括起来就可以了。

    key1 = "”" Roses are red Violets are blue"""

和C语言一样,如果希望多行内容不包含换行,可以用反斜杠放在一行的末尾:

# The following strings are byte-for-byte equivalent:
key1 = "The quick brown fox jumps over the lazy dog."

key2 = """
The quick brown \


  fox jumps over \
	the lazy dog."""

key3 = """\
       The quick brown \
       fox jumps over \
       the lazy dog.\
       """
  1. 字面字符串(Literal String) 何为"Literal String"其实就是所见即所得,不用转义的。TOML用“'”单引号来表示,比如将Windows的路径放到单引号中:

    What you see is what you get.

    winpath = ‘C:\Users\nodejs\templates’ winpath2 = ‘\ServerX\admin$\system32' quoted = ‘Tom “Dubs” Preston-Werner’ regex = ‘<\i\c*\s*>’

  2. 多行字面字符串 同样的,如果多行字符串里面不想转义,可以用三个单引号来引用:

    regex2 = ‘‘‘I [dw]on’t need \d{2} apples’’’ lines = '’' The first newline is trimmed in raw strings. All other whitespace is preserved. '''

整数

和一般程序语言中的整数一样,并支持现代化语言如Swift的中的西方千位置的助记符。

+99
42
0
-17
1_000  # 千位助记符
5_349_221

浮点数

和一般程序语言中的浮点数一样,同时也支持上面的千位助记符和科学计数法

# fractional
+1.0
3.1415
-0.01

# exponent
5e+22
1e6
-2E-2

# both
6.626e-34

9_224_617.445_991_228_313
1e1_000

布尔值

true表示真,false表示假

日期

TOML提供了日期类型,这种配置文件急需的类型,只要按照RFC 3339标准格式写就可以了:

1979-05-27T07:32:00Z
1979-05-27T00:32:00-07:00
1979-05-27T00:32:00.999999-07:00

数组

数组是通过"[]“括起来的同一类型的序列。并可以写在多行中:

[ 1, 2, 3 ]
[ "red", "yellow", "green" ]
[ [ 1, 2 ], [3, 4, 5] ]
[ "all", 'strings', """are the same""", '''type'''] # this is ok
[ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
[ 1, 2.0 ] # note: this is NOT ok
key = [
  1, 2, 3
]

key = [
  1,
  2, # this is ok
]

字典

字典通过一个”[]“中括号里面加上字典名表示,从这个中括号到下一个中括号或者文件结束表示一个字典的内容。

[table]
key = "value"
bare_key = "value"
bare-key = "value"

"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"

这里Kye可以用引号也可以不用引号,如果不用引号,那么Key只能是数字、字符、下划线或者破折号的组合。其他如点号什么的则需要用双引号。

通过在字典名中加入”.“号表示字典的字典:

[dog."tater.man"]
type = "pug"

表示JSON为

{ "dog": { "tater.man": { "type": "pug" } } }

这里字典名中的第一个“.”表示下一级字典,后面的句点用双引号括起来了,所以当做一般的Key对待。

既然是字典,那么key肯定不能重复,大家应该都理解,但是下面这种场景需要注意下:

[a]
b = 1  # key with "b"

[a.b]  # another key with "b"
c = 2

字典数组

上面基本介绍了TOML支持的所有格式,并且通过组合可以得到很多种数据内容。但是类似如下的JSON该怎么表示呢?

{
  "products": [
	{ "name": "Hammer", "sku": 738594937 },
	{ },
	{ "name": "Nail", "sku": 284758393, "color": "gray" }
  ]
}

TOML为此设计了一个专门的类型:字典数组

[[products]]
name = "Hammer"
sku = 738594937

[[products]]

[[products]]
name = "Nail"
sku = 284758393
color = "gray"

这里用两个”[[“表示一个数组,一个元素是字典的数组

再来看一个超级复杂的:

[[fruit]]
  name = "apple"

  [fruit.physical]
	color = "red"
	shape = "round"

  [[fruit.variety]]
	name = "red delicious"

  [[fruit.variety]]
	name = "granny smith"

[[fruit]]
  name = "banana"

  [[fruit.variety]]
  name = "plantain"

是不是有点晕,一点点拨开,其JSON表示为:

{
  "fruit": [
	{
      "name": "apple",
      "physical": {
        "color": "red",
        "shape": "round"
      },
      "variety": [
        { "name": "red delicious" },
        { "name": "granny smith" }
      ]
	},
	{
      "name": "banana",
      "variety": [
        { "name": "plantain" }
      ]
	}
  ]

}

总结

上面是在阅读TOML v4.0 Spec时的脚注,整个Spec才10页A4纸,基本看着就可以直接写内容了,不会像YAML一样,随便写就能写出语法错误。当然类似字典数组这些需要适应一下。总的来说TOML有INI的直观,也有JSON类似的灵活。