功能,示例,簡單的檔案,YAML的高級組件,語法,介紹,誕生,命名,功能,格式,多行縮進,單行縮寫,適用場景,腳本語言,序列化,配置檔案,語言比較,JSON,XML和SDL,縮排劃界,非階層式的資料模型,實際的考量,安全性,資料處理和呈現,函式庫,移植性,C語言,Perl,PHP,Python,Ruby,Java,R,JavaScript,.NET,OCaml,C++,Objective-C,Lua,Haskell,XML,Go,常見錯誤與使用細節,宿主語言,相關概念,討論,
功能
YAML的語法和其他高級語言類似,並且可以簡單表達清單、散列表,標量等數據形態。它使用空白符號縮進和大量依賴外觀的特色,特別適合用來表達或編輯數據結構、各種配置檔案、傾印調試內容、檔案大綱(例如:許多電子郵件標題格式和YAML非常接近)。儘管它比較適合用來表達層次結構式(hierarchical model)的數據結構,不過也有精緻的語法可以表示關係性(relational model)的數據。由於YAML使用空白字元和分行來分隔數據,使得它特別適合用
grep/
Python/
Perl/
Ruby操作。其讓人最容易上手的特色是巧妙避開各種封閉符號,如:引號、各種括弧等,這些符號在嵌套結構時會變得複雜而難以辨認。
示例
簡單的檔案
數據結構可以用類似大綱的縮進方式呈現
---receipt: Oz-Ware Purchase Invoicedate: 2012-08-06customer: given: Dorothy family: Gale items: - part_no: A4786 descrip: Water Bucket (Filled) price: 1.47 quantity: 4 - part_no: E1628 descrip: High Heeled "Ruby" Slippers size: 8 price: 133.7 quantity: 1bill-to: &id001 street: | 123 Tornado Alley Suite 16 city: East Centerville state: KSship-to: *id001 specialDelivery: > Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain....
注意在YAML中,字元串不一定要用雙引號標示。另外,在縮進中空白字元的數目並不是非常重要,只要相同層次結構的元素左側對齊就可以了(不過不能使用TAB字元)。這個檔案的頂層由七個鍵值組成:其中一個鍵值"items",是兩個元素構成的
數組(或稱
清單),這清單中的兩個元素同時也是包含了四個鍵值的散列表。檔案中重複的部分用這個方法處理:使用錨點(
&)和引用(
*)標籤將"bill-to"散列表的內容複製到"ship-to"散列表。也可以在檔案中加入選擇性的空行,以增加可讀性。在一個檔案中,可同時包含多個檔案,並用"
---"分隔。選擇性的符號"
..."可以用來表示檔案結尾(在利用流的通信中,這非常有用,可以在不關閉流的情況下,傳送結束信號)。
YAML的高級組件
這部分算是一個後續的討論,在比較各種數數據列語言時,YAML最常被提到的特色有兩個:關係樹和數據形態。
樹狀結構之間的互動引用
數據合併和參考
為了維持檔案的簡潔,並避免數據輸入的錯誤,YAML提供了結點參考(*)和散列合併(<<)參考到其他結點標籤的錨點標記(&)。參考會將樹狀結構加入錨點標記的內容,並可以在所有數據結構中運作(可以參考上面"ship-to"的示例)合併只有散列表可以使用,可以將鍵值自錨點標記複製到指定的散列表中。
當數據被instantiate合併和參考會被剖析器自動展開。
#眼部雷射手術之標準程式---- step: &id001 # 定義錨點標籤 &id001 instrument: Lasik 2000 pulseEnergy: 5.4 pulseDuration: 12 repetition: 1000 spotSize: 1mm- step: <<: *id001 # 合併鍵值:使用在錨點標籤定義的內容 spotSize: 2mm # 覆寫"spotSize"鍵值- step: <<: *id001 # 合併鍵值:使用在錨點標籤定義的內容 pulseEnergy: 500.0 # 覆寫鍵值 alert: > # 加入其他鍵值 warn patient of audible pop
數據形態
由於自動判定數據形態的功能,嚴格類型(也就是用戶有宣告的數據形態)很難在大部分的YAML檔案中看到。數據類型可以被區分成三大類:原碼(core),定義(defined),用戶定義(user-defined)。原碼可以自動被解析器分析(例如:浮點數,整數,字元串,清單,映射,...)。有一些高級的數據形態──例如比特數據──在YAML中有被“定義”,但不是每一種解析器都有支持。最後,YAML支持用戶自定的區域變數,包括:自定義的類別,結構或基本類型(例如:四倍精度的浮點數)。
強制轉型
YAML的自動判定數據形態是哪一種實體。但有時用戶會想要將數據強制轉型成自定的某種類型。最常見的狀況是字元串,有時候可能看起來像數字或布爾值,這種時候可以使用雙引號,或是使用嚴格類型標籤。
b: "123" # 字串(使用雙括弧)c: 123.0 # 浮點數d: !!float 123 # 浮點數,使用!!表達的嚴格型態e: !!str 123 # 字串,使用嚴格型態f: !!str Yes # 字串,使用嚴格型態g: Yes # 布林值"真"h: Yes we have No bananas # 字串(包含"Yes"和"No")
語法
在yaml.org(英文)可以找到輕巧而好用的
小抄(亦是用YAML表示)及格式說明。下面的內容,是關於基本組件的摘要。
使用空白字元為檔案縮進來表示結構;不過不能使用跳格字元(TAB)。
註解由井字號(#)開始,可以出現在一行中的任何位置,而且範圍只有一行(也就是一般所謂的單行註解)
每個清單成員以單行表示,並用短槓+空白(
- )起始。或使用
方括弧(
[]),並用
逗號+空白(
, )分開成員。
每個散列表的成員用冒號+空白(: )分開鍵值和內容。或使用大括弧({ }),並用逗號+空白(, )分開。
散列表的鍵值可以用
問號(
?)起始,用來明確的表示多個辭彙組成的鍵值。
字元串平常並不使用引號,但必要的時候可以用
雙引號(
")或
單引號(
')框住。
使用雙引號表示字元串時,可用倒斜線(
\)開始的轉義字元(這跟
C語言類似)表示特殊字元。
區塊的字元串用縮進和修飾符(非必要)來和其他數據分隔,有新行保留(preserve)(使用符號|)或新行摺疊(flod)(使用符號>)兩種方式。
在單一檔案中,可用連續三個
連字號(
---)區分多個檔案。
重複的內容可使從參考標記
星號(
*)複製到錨點標記(
&)。
指定格式可以使用兩個
驚嘆號(
!!),後面接上名稱。
檔案中的單一檔案可以使用指導指令,使用方法是百分比符號(%)。有兩個指導指令在YAML1.1版中被定義:
YAML在使用逗號及冒號時,後面都必須接一個空白字元,所以可以在字元串或數值中自由加入分隔設定號(例如:5,280或http://www.wikipedia.org)而不需要使用引號。
另外還有兩個特殊符號在YAML中被
保留,有可能在未來的版本被使用--(
@)和(
`)。
介紹
誕生
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對用冒號“:”來分隔。樣例如下:
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能夠縮寫成這樣:
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,Go 。除了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、Awk、perl、ruby,和Python,來應急性的過濾YAML檔案時更加方便。
特別是與標記語言不同的,連續的YAML區塊導嚮往往是格式良好的YAML檔案本身。這使得很容易撰寫那種“在開始提取的具體記錄之前,不需要‘讀取全部檔案內容’”的解析器(通常需要平衡起始和關閉標籤、尋找引號和跳脫字元)。當處理一個單一靜態的,整個存在記憶體中的數據結構將很大,或為提取一個項目來重建的整個結構,代價相當昂貴的記錄檔,這種特性是相當方便的。
值得討論的是,儘管它的縮排方式似乎複雜化了深度很大的巢狀層次,YAML將縮排視為一個單一的空白,這可能會取得比其他標記語言更好的壓縮比。此外,極深的縮排可以完全避免的是:
安全性
YAML是純粹用來表達資料的語言,所以內部不會存
代碼注入的可執行命令。這代表剖析器會相當(至少)安全的解析檔案,而不用擔心潛在與執行命令相關的安全漏洞。舉例來說,JSON是JavaScript的子集,使用JavaScript本身的剖析器是相當誘人的,不過也造成許多代碼注入的漏洞。雖然在所有資料序列語言中,安全解析本質上是可能的,但可執行性卻正是這樣一個惡名昭彰的缺陷;而YAML缺乏相關的命令語言,可能相對安全。
資料處理和呈現
XML和YAML規範提供非常不同的邏輯模型來進行資料結點的展現、處理及儲存。
函式庫
移植性
簡單的YAML檔案(例如:簡單的鍵值對)不需要完整的YAML剖析器,便可以被RegEx解析。許多常用的程式語言──純用某個語言,讓函式庫具有可攜性──都有的YAML的產生器和剖析器。當效能比較重要時,也有許多和C語言綁定的函式庫可使用。
C語言
2007-06時,這個YAML的函式庫漸趨穩定,並被YAML格式作者推薦使用[13]。
這個實現支持大部分1.0版的格式,並且被廣泛的使用。它使用高階interpreted languages進行最佳化。在2005之後,這個專案已經不再更新,不過仍可使用。
Perl
一個通用的接口,被數個YAML剖析器使用。
YAML簡化版的實現。擁有小巧輕快的優點──比完整功能的YAML實現快上許多──並用純Perl寫成。
與SYCK函式庫綁定。提供快速,highly featured的YAML剖析器。
與LibYaml綁定。提供1.1版更好的相容性。
PHP
純PHP的實現。
與SYCK函式庫綁定。
為symfony項目重寫的Spyc, 可獨立使用, 可以產生和剖析YAML檔案。
Python
純Python,或可選用LibYAML的函式庫。
與SYCK綁定。
Ruby
從1.8版開始,YAML剖析器成為標準函式庫之一。以SYCK為基礎。
with full UTF-8 support
Java
以Syck為基礎,and patterned off ruby-yaml
純Java的實現。
R
以SYCK為基礎。
JavaScript
原生的JavaScript即可產生YAML,但不能剖析。
產生和剖析。
.NET
待補充。
OCaml
C++
用C++將libYaml包裝。
Objective-C
Lua
Haskell
XML
currently draft only。
Go
常見錯誤與使用細節
建議使用能將跳格字元自動轉換成空白字元的編輯器,並且使用定寬度的字型。
編輯器要能正確的處理UTF-8和UTF16編碼(或是使用純ASCII編碼──它同時是UTF-8的子集)。
YAML的字串不需使用引號,這可以避免使用複雜的轉義字元,以增加可讀性。然而,這有時也會導致錯誤,例如,字串本身是一個曖昧的字眼(像數字或布爾值);或在短句中意外的出現YAML的結構符號(常見的例子是由驚嘆號起始的句子,或是包含冒號-空白的句子:"!Caca de vaca!"、"Caution: lions ahead")。這在發布YAML檔案時並不造成困擾,但在製作小型指令碼和人工編輯檔案時,這問題還蠻常出現的。比較好的方法是善用區塊符號("|" or ">")而不要使用單行字串,來避免這種曖昧的表達方式。
宿主語言
相關概念
YAML沒有自己的數據類型的定義,而是使用實現語言的數據類型。
例如,上面的那個YAML配置,在不同語言中解析後得到的數據類型並不相同。
$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'));
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就太完美了。輕巧,敏捷,高效,簡便,通用。這才是理想中的數據模型。當然就現在而言,這還只是個理想。