toml 简介
toml
1. 简介
编程中经常需要使用配置文件,常见配置文件有用INI, XML, JSON, YAML 语言编写,它们的表达力越来越强,同时书写便捷性也在不断提升。
TOML 全称: Tom’s Obvious, Minimal Language, 对应中文为 Tom的(语义)明显、(配置)最小化的语言。
TOML 是前GitHub CEO, Tom Preston-Werner,于2013年创建的语言,其目标是成为一个小规模的易于使用和阅读的语义化配置文件格式。
TOML 被设计成可以无歧义地映射为哈希表, 而编程语言中都会有类似哈希表的数据结构,从而可以很容易的被各种语言解析。
需要注意: 此规范当前为0.4 版,仍然会发生很多变化。
2. 语法
toml 语法规范
- TOML是大小写敏感的。
- TOML文件需要是UTF-8 编码。
- 空格是指制表符(0x09) 或空格 (0x20)。
- 换行符是指LF(0x0A)或CRLF (0x0D0A)。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# 这是TOML文档示例. title = "TOML Example" "a b" = 'abc' # 复杂键 max_lever = 120 tax = 0.1 switch = true promotion_date = 2017-11-19T00:00:00-08:00 # 日期时间 array_demo = [1, 2, 3, 4] color_enable = ["red", "green", "yellow"] [database] server = "192.168.1.1" ports = [ 8001, 8001, 8002 ] connection_max = 5000 enabled = true [servers] # 你可以按你的意愿缩进。TOML并不关心你是用Tab还是空格。 [servers.alpha] ip = "10.0.0.1" dc = "eqdc10" [servers.beta] ip = "10.0.0.2" dc = "eqdc10" [[redis]] host = "192.168.1.21" port = "6379" [[redis]] host = "192.168.1.22" port = "6379" |
3. 变量类型
- 字符串
- 整数
- 浮点数
- 布尔
- 日期
- 数组
- 表
- 嵌套表
- 内联表
- 表数组
注释
用符号#来表示注释:
1 2 3 |
# I am a comment. Hear me roar. Roar. key = "value" # Yeah, you can do this. |
键名
键值对左边是键,右边是值。键名和值周围的空格都将被忽略,键、等号和值,一定要在同一行(有些值可以多行表示)
键可以是裸键,或者由双引号包括,不可以是单引号。
裸键 仅包含字母、数字、下划线和破折号。
引号键 遵循基本字符串的规则,可以使用更广泛的键名。除非有必要,否则建议使用裸键。
1 2 3 4 5 6 7 8 |
key = "value" bare_key = "value" # 裸键 bare-key = "value" "127.0.0.1" = "value" "character encoding" = "value" "ʎǝʞ" = "value" |
字符串
有四种表示方法:基本字符串、多行基本字符串、字面量和多行字面量。
基本字符串 双引号括起来的任意字符串,包含双引号、反斜杠和控制字符等转义字符。
1 2 |
"I'm a string. \"You can quote me\".Name\tJos\u00E9\nLocation\tSF." |
多行基本字符串 三个双引号括起来的字符串,允许换行,所以可以将很长的字符串分成多行。
1 2 3 4 |
key1 = """ Roses are red Violets are blue""" |
注意: 行尾存在\
时,将会删除当前位置到下个非空字符或结束界定符之间的所有空格(包括换行符),该特性可以用于编写长字符串。所有的转义字符在多行基本字符串有效。
1 2 3 4 5 6 7 8 |
# 以下每个字符串都是相同的 key1 = "The quick brown fox jumps over the lazy dog." key2 = """ The quick brown \ fox jumps over \ the lazy dog.""" |
字面量字符串的特点是不允许转义,有基本字面量字符串和多行字面量字符串。
字面量字符串 是被单引号包含的字符串,跟基本字符串一样,它们一定是以单行出现:
1 2 3 4 5 6 |
# 所见即所得 winpath = 'C:\Users\nodejs\templates' winpath2 = '\\ServerX\admin$\system32\' quoted = 'Tom "Dubs" Preston-Werner' regex = '<\i\c*\s*>' |
因为不支持转义,所以字面量字符串里面没有办法写单引号。但是可以在多行字面量字符串中使用。
多行字面量字符串 被三个单引号括起来的字符串,允许换行。
紧跟起始界定符的换行符会被剪掉。界定符之间的所有其他内容都会被按照原样解释而不会被转义。
1 2 3 4 5 6 7 8 |
regex2 = '''I [dw]on't need \d{2} apples''' lines = ''' The first newline is trimmed in raw strings. All other whitespace is preserved. ''' |
对于二进制数据,建议你使用Base64或其他适合的编码,比如ASCII或UTF-8编码。具体的处理取决于特定的应用。
整数
整数是没有小数点的数字。正数前面也可以用加号,负数需要用负号前缀。
1 2 3 4 5 |
+99 42 0 -17 |
对于大整数,可以用下划线提高可读性。每个下划线两边至少包含一个数字。
1 2 3 4 |
1_000 5_349_221 1_2_3_4_5 # 有效,但不建议这样写 |
前导零是不允许的。也不允许十六进制(Hex)、八进制(octal)和二进制形式。
TOML 中不能表示诸如“无穷”和“非数字”,不能用一串数字表示的值。数字范围是64位从−9,223,372,036,854,775,808 到9,223,372,036,854,775,807。
浮点数
一个浮点数由整数部分(可能是带有加号或减号前缀的)和小数部分和(或)指数部分组成的数。如果只有小数部分和指数部分,那么小数部分必须放在指数部分前面。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 小数 +1.0 3.1415 -0.01 # 指数 5e+22 1e6 -2E-2 # 小数和指数同时存在 6.626e-34 |
小数部分是指在小数点后面的一个或多个数字。
指数部分是指E(大写或小写)后面的整数部分(可能用加号或减号为前缀)
和整数类似,你可以用下划线来提高可读性。每个下划线两边至少包含一个数字。
1 2 3 |
9_224_617.445_991_228_313 1e1_000 |
数据精度为64位 (double)。
布尔值
布尔值是小写的true和false。
1 2 3 |
true false |
时间日期
时间日期是RFC 3339中的时间格式。
1 2 3 |
1979-05-27T07:32:00Z 1979-05-27T00:32:00-07:00 |
数组
数组是由方括号包括的数据类型,元素由逗号分隔,元素的数据类型不能混用(所有的字符串均为同一类型,但是整形和浮点型是两种类型)。
1 2 3 4 5 6 7 |
[ 1, 2, 3 ] [ "red", "yellow", "green" ] [ [ 1, 2 ], [3, 4, 5] ] [ "all", 'strings', """are the same""", '''type'''] # 这样可以 [ [ 1, 2 ], ["a", "b", "c"] ] # 这样可以 [ 1, 2.0 ] # 注: 这样不行 |
数组可以写成多行,解析时会忽略空格和换行符。结束括号之前可以存在逗号。
1 2 3 4 5 6 7 8 9 |
key = [ 1, 2, 3 ] key = [ 1, 2, # 这样可以 ] |
表
表(也被称为哈希表或字典)是键值对集合,且键值对是无序的。表名由方括号括起,自成一行。
表的范围是在表名之下,直到下一个表或文件尾(EOF)之间都是该表的键值对。
表和数组相区分,数组里只有值。
1 2 |
[table] |
嵌套表
使用点(.)来表示嵌套表,点前面的部分属于父表,点后面的部分属于子表。
1 2 3 |
[dog.tater] type = "pug" |
等价于如下JSON格式:
1 2 |
{"dog":{"tater":{"type":"pug"}}} |
编写时,你可以不用定义每一层父表(super-tables)。
1 2 3 4 5 |
# [x] 你 # [x.y] 不 # [x.y.z] 需要这些 [x.y.z.w] # 没有键值对的空表是允许的 |
只要父表没有被直接定义,而且没有定义特定的键,你可以继续写入。
1 2 3 4 5 6 |
[a.b] c = 1 [a] d = 2 |
你不能多次定义键或表。这样做是无效的。
1 2 3 4 5 6 7 |
# 不要这么做 [a] b = 1 [a] # 重复定义表 a c = 2 |
1 2 3 4 5 6 7 |
# 也不要这样做 [a] b = 1 [a.b] # 重复定义键 b c = 2 |
被点分隔部分周围的空格都会被忽略,但是最好不要使用任何多余的空格
1 2 |
[ g . h . i ] # same as [g.h.i] |
所有的表名和键一定不能为空
1 2 3 4 5 6 7 8 |
# 无效TOML [] [a.] [a..b] [.b] [.] = "no key name" # 不允许 |
内联表
内联表提供一种更紧凑的语法来表示表,内联表是由大括号{
和 }
括起来的,在大括号内可以存在零个或多个逗号分隔的键值对。
内联表里的键值对跟标准表里的键值对形式一样并且允许所有的值类型,包括内联表。
内联表一般以单行出现。不允许换行符出现在大括号之间,除非是包含在值中的有效字符。
即便如此,也强烈建议不要在把内联表分成多行。如果你有这种需求,那么你应该去用标准表。
1 2 3 |
name = { first = "Tom", last = "Preston-Werner" } point = { x = 1, y = 2 } |
对应标准表定义:
1 2 3 4 5 6 7 8 |
[name] first = "Tom" last = "Preston-Werner" [point] x = 1 y = 2 |
表数组
表数组使用双中括号包裹表名,使用相同双括号名的每个表都是数组中的元素。表的顺序跟书写顺序一致。没有键值对的双括号表会被当作空表。
1 2 3 4 5 6 7 8 9 10 11 |
[[products]] name = "Hammer" sku = 738594937 [[products]] [[products]] name = "Nail" sku = 284758393 color = "gray" |
等价于如下JSON格式:
1 2 3 4 5 6 7 8 |
{ "products": [ { "name": "Hammer", "sku": 738594937 }, { }, { "name": "Nail", "sku": 284758393, "color": "gray" } ] } |
你也能创建内嵌的表数组。只需要对子表使用相同的双括号语法就可以。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[[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" |
上面的TOML对应于下面的JSON格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "fruit": [ { "name": "apple", "physical": { "color": "red", "shape": "round" }, "variety": [ { "name": "red delicious" }, { "name": "granny smith" } ] }, { "name": "banana", "variety": [ { "name": "plantain" } ] } ] } |
PHP toml 解析演示
安装解析库
1 2 |
composer require yosymfony/toml |
解析示例
1 2 3 4 5 6 7 8 9 |
<?php require_once 'vendor/autoload.php'; use Yosymfony\Toml\Toml; $arr = Toml::parse('example.toml'); print_r($arr); |