YAML

用來表達資料序列的編程語言

YAML是“YAML不是一種標記語言”的外語縮寫(見前方參考資料原文內容);但為了強調這種語言以數據做為中心,而不是以置標語言為重點,而用返璞詞重新命名。它是一種直觀的能夠被電腦識別的數據序列化格式,是一個可讀性高並且容易被人類閱讀,容易和腳本語言交互,用來表達資料序列的編程語言

它是類似於標準通用標記語言的子集XML的數據描述語言,語法比XML簡單很多。

介紹


誕生

YAML參考了其他多種語言,包括:XML、C語言、PythonPerl以及電子郵件格式RFC2822。
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.在縮排中空白字元的數目並不是非常重要,只要相同階層的元素左側對齊就可以了(不過不能使用TAB字元);
3.允許在文件中加入選擇性的空行,以增加可讀性;
4.在一個檔案中,可同時包含多個文件,並用“——”分隔;
5.選擇性的符號“...”可以用來表示檔案結尾(在利用串流的通訊中,這非常有用,可以在不關閉串流的情況下,發送結束訊號)。

單行縮寫

YAML也有用來描述好幾行相同結構的數據的縮寫語法,數組用'[]'包括起來,hash用'{}'來包括。因此,上面的這個YAML能夠縮寫成這樣:

適用場景


腳本語言

由於實現簡單,解析成本很低,YAML特別適合在腳本語言中使用。列一下現有的語言實現:Ruby,Java,Perl,Python,PHP,OCamlJavaScriptGo。除了Java 和 Go,其他都是腳本語言。

序列化

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、Awkperlruby,和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格式作者推薦使用。
• 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。

Go

• Go-yaml

常見錯誤與使用細節

• 編輯器
建議使用能將跳格字元自動轉換成空白字元的編輯器,並且使用定寬度的字型。
編輯器要能正確的處理UTF-8和UTF16編碼(或是使用純ASCII編碼──它同時是UTF-8的子集)。
• 字串
YAML的字串不需使用引號,這可以避免使用複雜的轉義字元,以增加可讀性。然而,這有時也會導致錯誤,例如,字串本身是一個曖昧的字眼(像數字或布爾值);或在短句中意外的出現YAML的結構符號(常見的例子是由驚嘆號起始的句子,或是包含冒號-空白的句子:"!Caca de vaca!"、"Caution: lions ahead")。這在發布YAML檔案時並不造成困擾,但在製作小型指令碼和人工編輯檔案時,這問題還蠻常出現的。比較好的方法是善用區塊符號("|" or ">")而不要使用單行字串,來避免這種曖昧的表達方式。
• 預期實做的特性

宿主語言


相關概念

YAML沒有自己的數據類型的定義,而是使用實現語言的數據類型。
例如,上面的那個YAML配置,在不同語言中解析后得到的數據類型並不相同。
• PHP
• PYTHON

討論

這一點,有可能是出奇制勝的地方,也可能是一個敗筆。如果兼容性保證的不好的話,YAML數據在不同語言間流轉會有問題。如果兼容性好的話,YAML就會成為不同語言間數據流通的橋樑。建議YAML官方設立兼容認證機制,每個語言的實現必須通過認證。
假如兼容性沒問題的話,YAML就太完美了。輕巧,敏捷,高效,簡便,通用。這才是理想中的數據模型。當然就現在而言,這還只是個理想。