toml官方wik
toml官方檔案
此次檔案是以v1.0.0為例,進行說明的,如果使用到的版本不同,直接去官方檔案中找對應的版本即可,
談到組態檔,大家都能說出來好幾種,比如常見的ini、xml、json、yaml、properties、toml等等,因為專案中用到了toml格式的組態檔,但是之前并沒有使用過,所以特意找toml官方檔案學習學習,特意記錄下,和官方提供的簡體中文一模一樣,
TOML是前GitHub CEO, Tom Preston-Werner,于2013年創建的語言,其目標是成為一個小規模的易于使用的語意化組態檔格式,TOML被設計為可以無二義性的轉換為一個哈希表(Hash table),TOML 應該能很容易地被決議成各種語言中的資料結構,
其實大家可以直接去看官方檔案,提供了對應中文的翻譯,比較友好的,感覺看官方檔案或者這篇文章,然后加上下面的兩個在線轉換的工具,toml格式的組態檔基本上就懂了,記不住的時候,看一看官方檔案就可以了,
在線TOML轉JSON工具
toml-to-json
-
TOML 檔案使用
.toml擴展名, -
在互聯網上傳輸 TOML 檔案時,恰當的 MIME 型別是
application/toml,
1、TOML 介紹
1.1 規范
- TOML 是大小寫敏感的,
- TOML 檔案必須是合法的 UTF-8 編碼的 Unicode 檔案,
- 空白是指制表符(0x09)或空格(0x20),
- 換行是指 LF(0x0A)或 CRLF(0x0D 0x0A),
1.2 注釋
使用#來表示注釋開始,至當前行尾結束,但是#出現在字串中時則無效,
# 這是一個全行注釋
key = "value" # 這是一個行末注釋
another = "# 這不是一個注釋"
除制表符以外的控制字符(U+0000 至 U+0008,U+000A 至 U+001F,U+007F)不允許出現在注釋中,
1.3 鍵值對
TOML 檔案最基本的構成區塊是鍵值對,
鍵名在等號的左邊而值在右邊,
鍵名和鍵值周圍的空白會被忽略,
鍵、等號和值必須在同一行(不過有些值可以跨多行),
key = "value"
值必須是下述型別之一,
- 字串
- 整數
- 浮點數
- 布林值
- 坐標日期時刻
- 各地日期時刻
- 各地日期
- 各地時刻
- 陣列
- 行內表
不指定值是非法的,
key = # 非法
鍵值對后必須換行(或結束檔案),
(例外見行內表)
first = "Tom" last = "Preston-Werner" # 非法
1.4 鍵名
鍵名可以是裸露的,引號引起來的,或點分隔的,
裸鍵只能包含 ASCII 字母,ASCII 數字,下劃線和短橫線(A-Za-z0-9_-),
注意裸鍵允許僅由純 ASCII 數字構成,例如 1234,但總是被解釋為字串,
key = "value"
bare_key = "value"
bare-key = "value"
1234 = "value"
引號鍵遵循與基本字串或字面量字串相同的規則并允許你使用更為廣泛的鍵名,
除非明顯必要,使用裸鍵方為最佳實踐,
"127.0.0.1" = "value"
"character encoding" = "value"
"???" = "value"
'key2' = "value"
'quoted "value"' = "value"
裸鍵不能為空,但空引號鍵是允許的(雖然不建議如此),
= "no key name" # 非法
"" = "blank" # 合法但不鼓勵
'' = 'blank' # 合法但不鼓勵
點分隔鍵是一系列通過點相連的裸鍵或引號鍵,
這允許了你將相近屬性放在一起:
name = "Orange"
physical.color = "orange"
physical.shape = "round"
site."google.com" = true
等價于 JSON 的如下結構:
{
"name": "Orange",
"physical": {
"color": "orange",
"shape": "round"
},
"site": {
"google.com": true
}
}
有關點分隔鍵定義表的詳細資訊,請參閱后文表一節,
點分隔符周圍的空白會被忽略,
不過,最佳實踐是不要使用任何不必要的空白,
fruit.name = "banana" # 這是最佳實踐
fruit. color = "yellow" # 等同于 fruit.color
fruit . flavor = "banana" # 等同于 fruit.flavor
縮進被作為空白對待而被忽略,
多次定義同一個鍵是非法的,
# 不要這樣做
name = "Tom"
name = "Pradyun"
注意裸鍵和引號鍵是等價的:
# 這是不可行的
spelling = "favorite"
"spelling" = "favourite"
只要一個鍵還沒有被直接定義過,你就仍可以對它和它下屬的鍵名賦值,
# 這使“fruit”鍵作為表存在,
fruit.apple.smooth = true
# 所以接下來你可以像這樣對“fruit”表添加內容:
fruit.orange = 2
# 以下是非法的
# 這將 fruit.apple 的值定義為一個整數,
fruit.apple = 1
# 但接下來這將 fruit.apple 像表一樣對待了,
# 整數不能變成表,fruit.apple 上面已經定義為整數了,就不能當做表使用,
fruit.apple.smooth = true
不鼓勵跳躍式地定義點分隔鍵,
# 合法但不鼓勵
apple.type = "水果"
orange.type = "水果"
apple.skin = "薄"
orange.skin = "厚"
apple.color = "紅"
orange.color = "橙"
# 建議
apple.type = "水果"
apple.skin = "薄"
apple.color = "紅"
orange.type = "水果"
orange.skin = "厚"
orange.color = "紅"
由于裸鍵可以僅由 ASCII 整陣列成,所以可能寫出看起來像浮點數、但實際上是兩部分的點分隔鍵,
除非你有充分的理由(基本不太會),否則不要這樣做,
3.14159 = "派"
上面的 TOML 對應以下 JSON,
{ "3": { "14159": "派" } }
1.5 字串
共有四種方式來表示字串:基本字串、多行基本字串、字面量和多行字面量,
所有字串都只能包含有效的 UTF-8 字符,
基本字串由引號(")包裹,
任何 Unicode 字符都可以使用,除了那些必須轉義的:引號,反斜杠,以及除制表符外的控制字符(U+0000 至 U+0008,U+000A 至 U+001F,U+007F),
str = "我是一個字串,\"你可以把我引起來\",姓名\tJos\u00E9\n位置\t舊金山,"
為了方便,一些流行的字符有其簡便轉義寫法,
\b - backspace (U+0008)
\t - tab (U+0009)
\n - linefeed (U+000A)
\f - form feed (U+000C)
\r - carriage return (U+000D)
\" - quote (U+0022)
\\ - backslash (U+005C)
\uXXXX - unicode (U+XXXX)
\UXXXXXXXX - unicode (U+XXXXXXXX)
任何 Unicode 字符都可以用 \uXXXX 或 \UXXXXXXXX 的形式來轉義,
轉義碼必須是有效的 Unicode 標量值,
所有上面未列出的其它轉義序列都是保留的;如果用了,TOML 應當產生錯誤,
有時你需要表示一小篇文本(例如譯文)或者想要對非常長的字串進行折行,
TOML 對此進行了簡化,
多行基本字串由三個引號包裹,允許折行,
緊隨開頭引號的那個換行會被去除,
其它空白和換行會被原樣保留,
str1 = """
Roses are red
Violets are blue"""
TOML 決議器可以相對靈活地決議成對所在平臺有效的換行字符,
# 在 Unix 系統,上面的多行字串可能等同于:
str2 = "Roses are red\nViolets are blue"
# 在 Windows 系統,它可能等價于:
str3 = "Roses are red\r\nViolets are blue"
想書寫長字串卻不想引入無關空白,可以用“行末反斜杠”,
當一行的最后一個非空白字符是未被轉義的 \ 時,它會連同它后面的所有空白(包括換行)一起被去除,直到下一個非空白字符或結束引號為止,
所有對基本字串有效的轉義序列,對多行基本字串也同樣適用,
# 下列字串的每一個位元組都完全相同:
str1 = "The quick brown fox jumps over the lazy dog."
str2 = """
The quick brown \
fox jumps over \
the lazy dog."""
str3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
任何 Unicode 字符都可以使用,除了那些必須被轉義的:反斜杠和除制表符、換行符、回車符外的控制字符(U+0000 至 U+0008,U+000B,U+000C,U+000E 至 U+001F,U+007F),
你可以在多行基本字串內的任何地方寫一個引號或兩個毗連的引號,
它們也可以寫在緊鄰界分符內的位置,
str4 = """這有兩個引號:"",夠簡單,"""
# str5 = """這有三個引號:""",""" # 非法
str5 = """這有三個引號:""\","""
str6 = """這有十五個引號:""\"""\"""\"""\"""\","""
# "這,"她說,"只是個無意義的條款,"
str7 = """"這,"她說,"只是個無意義的條款,""""
如果你常常要指定 Windows 路徑或正則運算式,那么必須轉義反斜杠就馬上成為啰嗦而易錯的了,
為了幫助搞定這點,TOML 支持字面量字串,它完全不允許轉義,
字面量字串由單引號包裹,
類似于基本字串,他們只能表現為單行:
# 所見即所得,
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
由于沒有轉義,無法在由單引號包裹的字面量字串中寫入單引號,
萬幸,TOML 支持一種多行版本的字面量字串來解決這個問題,
多行字面量字串兩側各有三個單引號來包裹,允許換行,
類似于字面量字串,無論任何轉義都不存在,
緊隨開始標記的那個換行會被剔除,
開始結束標記之間的所有其它內容會原樣對待,
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
原始字串中的
第一個換行被剔除了,
所有其它空白
都保留了,
'''
你可以在多行字面量字串中的任何位置寫一個或兩個單引號,但三個以上的單引號序列不可以,
quot15 = '''這有十五個引號:"""""""""""""""'''
# apos15 = '''這有十五個撇號:'''''''''''''''''' # 非法
apos15 = "這有十五個撇號:'''''''''''''''"
# '那,'她說,'仍然沒有意義,'
str = ''''那,'她說,'仍然沒有意義,''''
除制表符以外的所有控制字符都不允許出現在字面量字串中,
因此,對于二進制資料,建議你使用 Base64 或其它合適的 ASCII 或 UTF-8 編碼,
對那些編碼的處理方式,將交由應用程式自己來確定,
1.6 整數
整數是純數字,
正數可以以加號為前綴,
負數以減號為前綴,
int1 = +99
int2 = 42
int3 = 0
int4 = -17
對于大數,你可以在數字之間用下劃線來增強可讀性,
每個下劃線兩側必須至少有一個數字,
int5 = 1_000
int6 = 5_349_221
int7 = 53_49_221 # 印度記數體系分組
int8 = 1_2_3_4_5 # 合法但不鼓勵
前導零是不允許的,
整數值 -0 與 +0 是有效的,并等同于無前綴的零,
非負整數值也可以用十六進制、八進制或二進制來表示,
在這些格式中,+?不被允許,而(前綴后的)前導零是允許的,
十六進制值大小寫不敏感,
數字間的下劃線是允許的(但不能存在于前綴和值之間),
# 帶有 `0x` 前綴的十六進制
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef
# 帶有 `0o` 前綴的八進制
oct1 = 0o01234567
oct2 = 0o755 # 對于表示 Unix 檔案權限很有用
# 帶有 `0b` 前綴的二進制
bin1 = 0b11010110
任何 64 位有符號整數(從 ?2^63 到 2^63?1)都應當被接受并無損處理,
如果無法無損表現某個整數,則必須拋出錯誤,
1.7 浮點數
浮點數應當被實作為 IEEE 754 binary64 值,
一個浮點數由一個整數部分(遵從與十進制整數值相同的規則)后跟上一個小數部分和/或一個指數部分組成,
如果小數部分和指數部分兼有,那小數部分必須在指數部分前面,
# 小數
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01
# 指數
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2
# 都有
flt7 = 6.626e-34
小數部分是一個小數點后跟一個或多個數字,
一個指數部分是一個 E(大小寫均可)后跟一個整數部分(遵從與十進制整數值相同的規則,但可以包含前導零),
小數點,如果有用到的話,每側必須緊鄰至少一個數字,
# 非法的浮點數
invalid_float_1 = .7
invalid_float_2 = 7.
invalid_float_3 = 3.e+20
與整數相似,你可以使用下劃線來增強可讀性,
每個下劃線必須被至少一個數字圍繞,
flt8 = 224_617.445_991_228
浮點數值 -0.0 與 +0.0 是有效的,并且應當遵從 IEEE 754,
特殊浮點值也能夠表示,
它們是小寫的,
# 無窮
sf1 = inf # 正無窮
sf2 = +inf # 正無窮
sf3 = -inf # 負無窮
# 非數
sf4 = nan # 實際上對應信號非數碼還是靜默非數碼,取決于實作
sf5 = +nan # 等同于 `nan`
sf6 = -nan # 有效,實際碼取決于實作
1.8 布林值
布林值就是你所慣用的那樣,
要小寫,
bool1 = true
bool2 = false
1.9 坐標日期時刻
要準確地表示世上的一個特定時間,你可以使用指定了時區偏移量的 RFC 3339 格式的日期時刻,
odt1 = 1979-05-27T07:32:00Z
odt2 = 1979-05-27T00:32:00-07:00
odt3 = 1979-05-27T00:32:00.999999-07:00
出于可讀性的目的,你可以用一個空格字符替代日期和時刻之間的 T(RFC 3339 的第 5.6 節中允許了這樣做),
odt4 = 1979-05-27 07:32:00Z
毫秒級的精度是必須的,
更高精度的小數秒取決于實作,
如果它的值超出了實作所支持的精度,那超出的部分必須被舍棄,而不能四舍五入,
1.10 各地日期時刻
如果你省略了 RFC 3339 日期時刻中的時區偏移量,這表示該日期時刻的使用并不涉及時區偏移,
在沒有其它資訊的情況下,并不知道它究竟該被轉化成世上的哪一刻,
如果仍被要求轉化,那結果將取決于實作,
ldt1 = 1979-05-27T07:32:00
ldt2 = 1979-05-27T00:32:00.999999
毫秒級的精度是必須的,
更高精度的小數秒取決于實作,
如果它的值超出了實作所支持的精度,那多余的部分必須被舍棄,而不能四舍五入,
1.11 各地日期
如果你只寫了 RFC 3339 日期時刻中的日期部分,那它表示一整天,同時也不涉及時區偏移,
ld1 = 1979-05-27
1.12 各地時刻
如果你只寫了 RFC 3339 日期時刻中的時刻部分,它將只表示一天之中的那個時刻,而與任何特定的日期無關、亦不涉及時區偏移,
lt1 = 07:32:00
lt2 = 00:32:00.999999
毫秒級的精度是必須的,
更高精度的小數秒取決于實作,
如果它的值超出了實作所支持的精度,那多余的部分必須被舍棄,而不能四舍五入,
1.13 陣列
陣列是內含值的方括號,
空白會被忽略,
子元素由逗號分隔,
陣列可以包含與鍵值對所允許的相同資料型別的值,
可以混合不同型別的值,
integers = [ 1, 2, 3 ]
colors = [ "紅", "黃", "綠" ]
nested_array_of_ints = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "所有的", '字串', """是相同的""", '''型別''' ]
# 允許混合型別的陣列
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
"Foo Bar <[email protected]>",
{ name = "Baz Qux", email = "[email protected]", url = "https://example.com/bazqux" }
]
陣列可以跨行,
陣列的最后一個值后面可以有終逗號(也稱為尾逗號),
值、逗號、結束括號前可以存在任意數量的換行和注釋,
陣列值和逗號之間的縮進被作為空白對待而被忽略,
integers2 = [
1, 2, 3
]
integers3 = [
1,
2, # 這是可以的
]
1.14 表
表(也被稱為哈希表或字典)是鍵值對的集合,
它們由表頭定義,連同方括號作為單獨的行出現,
看得出表頭不同于陣列,因為陣列只有值,
[table]
在它下方,直至下一個表頭或檔案結束,都是這個表的鍵值對,
表不保證保持鍵值對的指定順序,
[table-1]
key1 = "some string"
key2 = 123
[table-2]
key1 = "another string"
key2 = 456
表名的規則與鍵名相同(見前文鍵名定義),
[dog."tater.man"]
type.name = "pug"
等價于 JSON 的如下結構:
{ "dog": { "tater.man": { "type": { "name": "pug" } } } }
鍵名周圍的空格會被忽略,
然而,最佳實踐還是不要有任何多余的空白,
[a.b.c] # 這是最佳實踐
[ d.e.f ] # 等同于 [d.e.f]
[ g . h . i ] # 等同于 [g.h.i]
[ j . "?" . 'l' ] # 等同于 [j."?".'l']
縮進被作為空白對待而被忽略,
你不必層層完整地寫出你想寫的所有途徑的父表,
TOML 知道該怎么辦,
# [x] 你
# [x.y] 不
# [x.y.z] 需要這些
[x.y.z.w] # 來讓這生效
[x] # 后置父表定義是可以的
空表是允許的,只要里面沒有鍵值對就行了,
類似于鍵名,你不能重復定義一個表,
這樣做是非法的,
# 不要這樣做
[fruit]
apple = "紅"
[fruit]
orange = "橙"
# 也不要這樣做
[fruit]
apple = "紅"
[fruit.apple]
texture = "光滑"
不鼓勵無序地定義表,
# 有效但不鼓勵
[fruit.apple]
[animal]
[fruit.orange]
# 推薦
[fruit.apple]
[fruit.orange]
[animal]
頂層表,又被稱為根表,于檔案開始處開始并在第一個表頭(或檔案結束處)前結束,
不同于其它表,它沒有名字且無法后置,
# 頂層表開始,
name = "Fido"
breed = "pug"
# 頂層表結束,
[owner]
name = "Regina Dogman"
member_since = 1999-08-04
點分隔鍵為最后一個鍵名前的每個鍵名創建并定義一個表,倘若這些表尚未被創建的話,
fruit.apple.color = "red"
# 定義一個名為 fruit 的表
# 定義一個名為 fruit.apple 的表
fruit.apple.taste.sweet = true
# 定義一個名為 fruit.apple.taste 的表
# fruit 和 fruit.apple 已經創建過了
由于表不能定義多于一次,不允許使用 [table] 頭重定義這樣的表,
同樣地,使用點分隔鍵來重定義已經以 [table] 形式定義過的表也是不允許的,
不過,[table] 形式可以被用來定義通過點分隔鍵定義的表中的子表,
[fruit]
apple.color = "紅"
apple.taste.sweet = true
# [fruit.apple] # 非法
# [fruit.apple.taste] # 非法
[fruit.apple.texture] # 你可以添加子表
smooth = true
1.15 行內表
行內表提供了一種更為緊湊的語法來表示表,
它們對于分組資料特別有用,否則這些資料很快就會變得冗長,
行內表被完整地定義在花括號之中:{ 和 }, 括號中,可以出現零或多個以逗號分隔的鍵值對,
鍵值對采取與標準表中的鍵值對相同的形式,
什么型別的值都可以,包括行內表,
行內表得出現在同一行內,
行內表中,最后一對鍵值對后不允許終逗號(也稱為尾逗號),
不允許花括號中出現任何換行,除非在值中它們合法,
即便如此,也強烈不建議把一個行內表搞成縱跨多行的樣子,
如果你發現自己真的需要,那意味著你應該使用標準表,
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type.name = "pug" }
上述行內表等同于下面的標準表定義:
[name]
first = "Tom"
last = "Preston-Werner"
[point]
x = 1
y = 2
[animal]
type.name = "pug"
行內表是獨立自足的,在內部定義全部的鍵與子表,
不能在括號以外的地方,再添加鍵與子表,
[product]
type = { name = "Nail" }
# type.edible = false # 非法
類似地,行內表不能被用于向一個已定義的表添加鍵或子表,
[product]
type.name = "Nail"
# type = { edible = false } # 非法
1.16 表陣列
最后一個還沒講到的語法允許你寫表陣列,
這可以通過把表名寫在雙方括號里的表頭來表示,
表頭的第一例定義了這個陣列及其首個表元素,而后續的每個則在該陣列中創建并定義一個新的表元素,
這些表按出現順序插入該陣列,
[[products]]
name = "Hammer"
sku = 738594937
[[products]] # 陣列里的空表
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
等價于 JSON 的如下結構,
{
"products": [
{ "name": "Hammer", "sku": 738594937 },
{ },
{ "name": "Nail", "sku": 284758393, "color": "gray" }
]
}
任何對表陣列的參考都指向該陣列里最近定義的表元素,
這允許你在最近的表內定義子表,甚至子表陣列,
[[fruits]]
name = "apple"
[fruits.physical] # 子表
color = "red"
shape = "round"
[[fruits.varieties]] # 嵌套表陣列
name = "red delicious"
[[fruits.varieties]]
name = "granny smith"
[[fruits]]
name = "banana"
[[fruits.varieties]]
name = "plantain"
上述 TOML 等價于 JSON 的如下結構,
{
"fruits": [
{
"name": "apple",
"physical": {
"color": "red",
"shape": "round"
},
"varieties": [
{ "name": "red delicious" },
{ "name": "granny smith" }
]
},
{
"name": "banana",
"varieties": [
{ "name": "plantain" }
]
}
]
}
如果一個表或表陣列的父級是一個陣列元素,該元素必須在定義子級前先定義,
順序顛倒的行為,在決議時報錯,
# 非法的 TOML 檔案
[fruit.physical] # 子表,但它應該隸屬于哪個父元素?
color = "red"
shape = "round"
[[fruit]] # 決議器必須在發現“fruit”是陣列而非表時拋出錯誤
name = "apple"
若試圖向一個靜態定義的陣列追加內容,即便陣列尚且為空,也必須在決議時報錯,
# 非法的 TOML 檔案
fruits = []
[[fruits]] # 不允許
若試圖用已經確定為陣列的名稱定義表,必須在決議時報錯,
將陣列重定義為普通表的行為,也必須在決議時報錯,
# 非法的 TOML 檔案
[[fruits]]
name = "apple"
[[fruits.varieties]]
name = "red delicious"
# 非法:該表與之前的表陣列相沖突
[fruits.varieties]
name = "granny smith"
[fruits.physical]
color = "red"
shape = "round"
# 非法:該表陣列與之前的表相沖突
[[fruits.physical]]
color = "green"
你也可以適當使用行內表:
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/550804.html
標籤:其他
下一篇:返回列表
