YAML是“另一種標記語言”的外語縮寫[1]
(見前方參考資料原文內容);但為了強調這種語言以數據做為中心,而不是以置標語言為重點,而用
返璞詞重新命名。它是一種直觀的能夠被電腦識別的數據序列化格式,是一個可讀性高並且容易被人類閱讀,容易和
腳本語言交互,用來表達資料序列的編程語言。
誕生
Clark Evans在2001年5月在首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。
命名
YAML是"YAML Ain't a Markup Language"(YAML不是一種置標語言)的遞歸縮寫。
在開發的這種語言時,YAML 的意思其實是:"Yet Another Markup Language"(仍是一種置標語言),
功能
YAML的語法和其他高階語言類似,並且可以簡單表達清單、散列表,標量等資料形態、。
它使用空白符號縮排和大量依賴外觀的特色,特別適合用來表達或編輯數據結構、各種設定檔、傾印除錯內容、文件大綱(例如:許多電子郵件標題格式和YAML非常接近)。
盡管它比較適合用來表達階層式(hierarchical model)的數據結構,不過也有精致的語法可以表示關聯性(relational model)的資料。
由於YAML使用空白字符和分行來分隔資料,使的他特別適合用grep、Python、Perl、Ruby操作。
其讓人最容易上手的特色是巧妙避開各種封閉符號,如:引號、各種括號等,這些符號在嵌套結構中會變得復雜而難以辨認。
多行縮進
數據結構可以用類似大綱的縮排方式呈現,結構通過縮進來表示,連續的項目通過減號“-”來表示,map結構里面的key/value對用冒號“:”來分隔。樣例如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
house:
family:
name: Doe
parents:
- John
- Jane
children:
- Paul
- Mark
- Simone
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345
|
注意:
-
字串不一定要用雙引號標識;
-
在縮排中空白字符的數目並不是非常重要,只要相同階層的元素左側對齊就可以了(不過不能使用TAB字符);
-
允許在文件中加入選擇性的空行,以增加可讀性;
-
在一個檔案中,可同時包含多個文件,並用“——”分隔;
-
選擇性的符號“...”可以用來表示檔案結尾(在利用串流的通訊中,這非常有用,可以在不關閉串流的情況下,發送結束訊號)。
單行縮寫
YAML也有用來描述好幾行相同結構的數據的縮寫語法,數組用'[]'包括起來,hash用'{}'來包括。因此,上面的這個YAML能夠縮寫成這樣:
|
1
2
3
|
house:
family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
address: { number:
34
, street: Main Street, city: Nowheretown, zipcode:
12345
}
|
腳本語言
由於實現簡單,解析成本很低,YAML特別適合在
腳本語言中使用。列一下現有的語言實現:Ruby,Java,Perl,Python,PHP,OCaml,JavaScript,除了Java,其他都是腳本語言。
序列化
YAML比較適合做序列化。因為它是
宿主語言數據類型直轉的。
配置文件
YAML做配置文件也不錯。寫YAML要比寫XML快得多(無需關注標簽或引號),並且比ini文檔功能更強。
比如Ruby on Rails的配置就選用的YAML。對ROR而言,這很自然,也很省事.
由於兼容性問題,不同語言間的數據流轉建議不要用YAML.
雖然YAML是參考JSON,XML和SDL等語言,不過跟這些語言比起來,YAML仍有自己的特色。
JSON
JSON的語法是YAML1.2版的子集,同時非常接近YAML1.0與1.1版的子集,因此大部分的JSON文件都可以被YAML的剖析器剖析。這是因為JSON的語法結構和YAML的內置格式相同。雖然大范圍的分層也可以使用類似JSON的內置格式,不過YAML標准並不建議這樣使用,除非這樣編寫能讓文件可讀性增加。YAML的許多擴展在JSON是找不到的,如:進階資料形態、關系錨點、字串不需要雙引號、映射資料形態會儲存鍵值的順序。
XML和SDL
XML和SDL標簽概念,在YAML中是找不到的。對於數據結構序列(盡管這是有爭議的),標簽屬性的特色就是可以將資料及復雜資料附加資訊分離,並將各種原生數據結構(如:雜湊表、陣列)用同一種語言表示。YAML則以資料的可擴展性作為替代。(包括為了模擬物件的類別型態)在YAML本身的規范中,並沒有類似XML的語言定義文件綱要(language-defined document schema descriptors)──例如驗證自己本身的結構是否正確的文件。不過,YAML綱要描述語言(YAML schema descriptor language)是存在的。另外還有YAXML──用XML描述YAML的結構──可以讓XML Schema與XSLT轉換程式應用在YAML之上。況且,在一般使用的情況下,YAML豐富的定義型態之語法已經提供了足夠的方式來辨認YAML文件是否正確。
縮排划界
由於YAML的運作主要依賴大綱式的縮排來決定結構,這有效解決了界定符沖突(Delimiter collision)的問題。YAML的資料形態不依賴引號之特點,使的YAML文件可以利用區塊,輕易的插入各種其他類型文件,如:XML、SDL、JSON,甚至插入另一篇YAML。
相反的,要將YAML置入XML或SDL中時,需要將所有空白字符和位勢符號(potential sigils,如:<,>和&)轉換成實體語法;要將YAML置入JSON中,需要用引號框住,並轉換內部的所有引號。
非階層式的資料模型
跟SDL、JSON等,每個子結點只能有單一一個父節點的階層式模型不同,YAML提供了一個簡單的關系體制,可以從樹狀結構的其他地方,重復相同的資料,而不必顯示那些冗余的結構。這點和XML中的IDRef類似,YAML剖析器在將YAML轉換成物件時,會自動將那些參考資料的結構展開,所以程式在使用時並不會查覺到哪些資料是解碼自這種結構。XML則不會將這種結構展開。這種表示法可以增加程式的可讀性,並且,在那種“大部分參數維持和上次相同,只有少數改變”的設定檔及通訊協定中,可以減少數據輸入錯誤。一個例子是:“送貨地點”和“購買地點”在發票的紀錄中幾乎都是相同的資料。
實際的考量
YAML是“行導向的”,因此,就算想由現有程序的混亂輸出,轉換成YAML格式,並保留大部分的原始文件之外觀,也非常簡單。因為他不需要平衡封閉的標簽、括號及引號,可以從很簡單的利用程式,從報表產生YAML。同樣,空格分隔可讓使用行導向的命令如:grep、Awk、perl、ruby,和Python,來應急性的過濾YAML文件時更加方便。
特別是與標記語言不同的,連續的YAML區塊導向往往是格式良好的YAML文件本身。這使得很容易撰寫那種“在開始提取的具體記錄之前,不需要‘讀取全部文件內容’”的解析器(通常需要平衡起始和關閉標簽、尋找引號和跳脫字符)。當處理一個單一靜態的,整個存在內存中的數據結構將很大,或為提取一個項目來重建的整個結構,代價相當昂貴的記錄檔,這種特性是相當方便的。
值得討論的是,盡管它的縮排方式似乎復雜化了深度很大的巢狀層次,YAML將縮排視為一個單一的空白,這可能會取得比其他標記語言更好的壓縮比。此外,極深的縮排可以完全避免的是:
-
使用“內置格式”(即簡稱類JSON格式)而無縮排;
-
使用關聯錨點展開階層以形成一個攤平的格式,使得YAML解析器能透明地重組成完整的數據結構。
安全性
YAML是純粹用來表達資料的語言,所以內部不會存
代碼注入的可執行命令。這代表剖析器會相當(至少)安全的解析文件,而不用擔心潛在與執行命令相關的安全漏洞。舉例來說,JSON是JavaScript的子集,使用JavaScript本身的剖析器是相當誘人的,不過也造成許多代碼注入的漏洞。雖然在所有資料序列語言中,安全解析本質上是可能的,但可執行性卻正是這樣一個惡名昭彰的缺陷;而YAML缺乏相關的命令語言,可能相對安全。
資料處理和呈現
XML和YAML規范提供非常不同的邏輯模型來進行資料結點的展現、處理及儲存。
移植性
簡單的YAML檔案(例如:簡單的鍵值對)不需要完整的YAML剖析器,便可以被RegEx解析。許多常用的編程語言──純用某個語言,讓函式庫具有可攜性──都有的YAML的產生器和剖析器。當效能比較重要時,也有許多和C語言綁定的函式庫可使用。
C語言
-
libYAML
2007-06時,這個YAML的函式庫漸趨穩定,並被YAML格式作者推薦使用[13]。
-
SYCK
這個實現支持大部分1.0版的格式,並且被廣泛的使用。它使用高階interpreted languages進行最佳化。在2005之后,這個專案已經不再更新,不過仍可使用。
Perl
-
YAML::
一個通用的接口,被數個YAML剖析器使用。
-
YAML::Tiny
YAML簡化版的實現。擁有小巧輕快的優點──比完整功能的YAML實現快上許多──並用純Perl寫成。
-
YAML::Syck
與SYCK函式庫綁定。提供快速,highly featured的YAML剖析器。
-
YAML::XS
與LibYaml綁定。提供1.1版更好的相容性。
PHP
-
Spyc
純PHP的實現。
-
PHP-Syck
與SYCK函式庫綁定。
-
sfYaml
為symfony項目重寫的Spyc, 可獨立使用, 可以產生和剖析YAML文件。
Python
-
PyYaml
純Python,或可選用LibYAML的函式庫。
-
PySyck
與SYCK綁定。
Ruby
從1.8版開始,YAML剖析器成為標准函式庫之一。以SYCK為基礎。
-
Ya2YAML
with full UTF-8 support
Java
-
jvyaml
以Syck為基礎,and patterned off ruby-yaml
-
JYaml
純Java的實現。
R
-
CRAN YAML
以SYCK為基礎。
JavaScript
原生的JavaScript即可產生YAML,但不能剖析。
-
YAML JavaScript
產生和剖析。
.NET
待補充。
OCaml
-
OCaml-Syck
C++
用C++將libYaml包裝。
Objective-C
-
Cocoa-Syck
Lua
-
Lua-Syck
Haskell
-
Haskell Reference wrappers
XML
-
YAXML
currently draft only。
常見錯誤與使用細節
-
編輯器
建議使用能將跳格字符自動轉換成空白字符的編輯器,並且使用定寬度的字型。
編輯器要能正確的處理UTF-8和UTF16編碼(或是使用純ASCII編碼──它同時是UTF-8的子集)。
-
字串
YAML的字串不需使用引號,這可以增加可讀性,並避免巢狀的跳脫字符。然而,這有時也會導致錯誤,例如,字串本身是一個曖昧的字眼(像數字或布林值);或在短句中意外的出現YAML的結構符號(常見的例子是由驚嘆號起始的句子,或是包含冒號-空白的句子:"!Caca de vaca!"、"Caution: lions ahead")。這在發布YAML檔案時並不造成困擾,但在制作小型指令碼和人工編輯檔案時,這問題還蠻常出現的。比較好的方法是善用區塊符號("|" or ">")而不要使用單行字串,來避免這種曖昧的表達示。
-
預期實做的特性
相關概念
YAML沒有自己的數據類型的定義,而是使用實現語言的數據類型。
例如,上面的那個YAML配置,在不同語言中解析后得到的數據類型並不相同。
-
PHP
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$house
=
array
(
'family'
=>
array
(
'name'
=>
'Doe'
,
'parents'
=>
array
(
'John'
,
'Jane'
),
'children'
=>
array
(
'Paul'
,
'Mark'
,
'Simone'
)
),
'address'
=>
array
(
'number'
=> 34,
'street'
=>
'Main Street'
,
'city'
=>
'Nowheretown'
,
'zipcode'
=>
'12345'
)
);
|
-
PYTHON
|
1
2
3
4
|
house = {
family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] },
address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }
}
|
討論
這一點, 有可能是出奇制勝的地方,也可能是一個敗筆。如果兼容性保證的不好的話,YAML數據在不同語言間流轉會有問題。如果兼容性好的話,YAML就會成為不同語言間數據流通的橋梁。建議YAML官方設立兼容認證機制,每個語言的實現必須通過認證。
假如兼容性沒問題的話,YAML就太完美了。輕巧,敏捷,高效,簡便,通用。這才是理想中的數據模型。當然就現在而言,這還只是個理想。
