YAML

YAML（/ˈjæməl/）是一個可讀性高，用來表達資料序列化的格式。YAML參考了其他多種語言，包括：C語言、Python、Perl，並從XML、電子郵件的數據格式（RFC 2822）中獲得靈感。Clark Evans在2001年首次發表了這種語言，另外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操作。其讓人最容易上手的特色是巧妙避開各種封閉符號，如：引號、各種括號等，這些符號在巢狀結構時會變得複雜而難以辨認。 資料結構可以用類似大綱的縮排方式呈現 --- receipt: Oz-Ware Purchase Invoice date: 2012-08-06 customer: 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: 1 bill-to: &id001 street: | 123 Tornado Alley Suite 16 city: East Centerville state: KS ship-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提供縮排／區塊以及內置（inline）兩種格式，來表示清單和雜湊表。以下展示幾種YAML的基本元件。 習慣上清單比較常用區塊格式（block format）表示，也就是用短槓+空白字元作為起始。 --- # 最喜愛的電影 - Casablanca - North by Northwest - Notorious 另外還有一種內置格式（inline format）可以選擇──用方括號圍住，並用逗號+空白區隔（類似JSON的語法）。 --- # 購物清單 [milk, pumpkin pie, eggs, juice] 鍵值和資料由冒號及空白字元分開。區塊形式（常使用於YAML數據文檔中）使用縮進和換行符分隔key: value對。內置形式（常使用於YAML數據串流中）在大括號中使用逗號+空白字元分隔key: value對。 --- # 區塊形式 name: John Smith age: 33 --- # 內置形式 {name: John Smith, age: 33} 再次強調，字串不需要包在引號之內。 有兩種語法可以書寫多行文字（multi-line strings），一種為保留換行（使用|字元），另一種為摺疊換行（使用>字元）。兩種語法在其特殊字元之後都必須接著換行。 data: | # 譯者注：這是一首著名的五行民謠(limerick) There once was a man from Darjeeling # 這裡曾有一個人來自大吉嶺 Who got on a bus bound for Ealing # 他搭上一班往伊靈的公車 It said on the door # 門上這麼說的 "Please don't spit on the floor" # "請勿在地上吐痰" So he carefully spat on the ceiling # 所以他小心翼翼的吐在天花板上 根據預設，每行開頭的縮排（以首行為基準）和行末空白會被去除，而不同的縮排會保留差異。 使用保留換行時，作為最後一行結尾的換行(\n)會包含在文本之內，若希望使用此縮排方式，但不想要含有最後的換行，可以使用Chomping Final Line Break。 data: |- # 譯者注：這是一首著名的五行民謠(limerick) There once was a man from Darjeeling # 這裡曾有一個人來自大吉嶺 Who got on a bus bound for Ealing # 他搭上一班往伊靈的公車 It said on the door # 門上這麼說的 "Please don't spit on the floor" # "請勿在地上吐痰" So he carefully spat on the ceiling # 所以他小心翼翼的吐在天花板上 data: > Wrapped text # 摺疊的文字 will be folded # 將會被收 into a single # 進單一一個 paragraph # 段落 Blank lines denote # 空白的行代表 paragraph breaks # 段落之間的區隔 和保留換行不同的是，只有空白行才視為換行，原本的換行字元會被轉換成空白字元，而行首縮排會被去除。 - {name: John Smith, age: 33} - name: Mary Smith age: 27 men: [John Smith, Bill Jones] women: - Mary Smith - Susan Williams 這部分算是一個後續的討論，在比較各種數資料列語言時，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的自動判定資料形態是哪一種實體。但有時使用者會想要將資料強迫轉型成自定的某種型態。最常見的狀況是字串，有時候可能看起來像數字或布林值，這種時候可以使用雙引號，或是使用嚴格型態標籤。 --- a: 123 # 整數 b: "123" # 字串（使用雙引號） c: 123.0 # 浮點數 d: !!float 123 # 浮點數，使用!!表達的嚴格型態 e: !!str 123 # 字串，使用嚴格型態 f: !!str Yes # 字串，使用嚴格型態 g: Yes # 布林值"真"（yaml1.1）或字串"Yes"（yaml1.2） h: Yes we have No bananas # 字串（包含"Yes"和"No"） 除了一般的資料形態之外，使用者也可以使用一些較為進階的型態，但不保證可被每種解析器分析。使用時和強迫轉型類似，要在形態名稱之前加上兩個驚嘆號（!!）。有幾種重要的形態在本篇沒有討論，包括集合（sets），有序映照（ordered maps），時間戳記（timestamps）以及十六進位資料（hexadecimal）。下面這個範例則是位元資料（binary） --- picture: !!binary | R0lGODdhDQAIAIAAAAAAANn Z2SwAAAAADQAIAAACF4SDGQ ar3xxbJ9p0qa7R0YxwzaFME 1IAADs= 許多YAML的實現允許使用者自訂資料形態。在將一個物件序列化時，這個方法還頗方便的。某些區域資料形態可能不存在預設的資料形態中，不過這種型態在特定的YAML應用程式中是有定義的。這種區域資料形態用驚嘆號（ ! ）表示。 --- myObject: !myClass { name: Joe, age: 15} 在yaml.org（英文）可以找到輕巧而好用的小抄（亦是用YAML表示）及格式說明。下面的內容，是關於基本元件的摘要。 YAML使用可列印的Unicode字元，可使用UTF-8或UTF-16。 使用空白字元為文件縮排來表示結構；不過不能使用跳格字元(TAB)。 註解由井字號（ # ）開始，可以出現在一行中的任何位置，而且範圍只有一行（也就是一般所謂的單行註解） 每個清單成員以單行表示，並用短槓+空白（ -   ）起始。或使用方括號（ [ ] ），並用逗號+空白（ ,   ）分開成員。 每個雜湊表的成員用冒號+空白（ :   ）分開鍵值和內容。或使用大括號（ {   } ），並用逗號+空白（ ,   ）分開。 雜湊表的鍵值可以用問號 ( ? )起始，用來明確的表示多個詞彙組成的鍵值。 字串平常並不使用引號，但必要的時候可以用雙引號 ( " )或單引號 ( ' )框住。 使用雙引號表示字串時，可用倒斜線（ \ ）開始的跳脫字元（這跟C語言類似）表示特殊字元。 區塊的字串用縮排和修飾詞（非必要）來和其他資料分隔，有新行保留（preserve）（使用符號 | ）或新行摺疊（flod）（使用符號 > ）兩種方式。 在單一檔案中，可用連續三個連字號（---）區分多個檔案。 另外，還有選擇性的連續三個點號（ ... ）用來表示檔案結尾。 重複的內容可使從參考標記星號 ( * )複製到錨點標記（ & ）。 指定格式可以使用兩個驚嘆號 ( !! )，後面接上名稱。 檔案中的單一文件可以使用指導指令，使用方法是百分比符號( % )。有兩個指導指令在YAML1.1版中被定義： %YAML 指導指令，用來識別文件的YAML版本。 %TAG 指導指令，被用在URI的字首標記。這個方法在標記節點的型態時相當有用。 YAML在使用逗號及冒號時，後面都必須接一個空白字元，所以可以在字串或數值中自由加入分隔符號（例如：5,280或http://www.wikipedia.org）而不需要使用引號。 另外還有兩個特殊符號在YAML中被保留，有可能在未來的版本被使用--（ @ ）和（ ` ）。 雖然YAML是參考JSON，XML和SDL等語言，不過跟這些語言比起來，YAML仍有自己的特色。 JSON的語法是YAML1.2版的子集,，同時非常接近 YAML1.0與1.1版的子集，因此大部分的JSON文件都可以被YAML的剖析器剖析。這是因為JSON的語法結構和YAML的內置格式相同。雖然大範圍的分層也可以使用類似JSON的內置格式，不過YAML標準並不建議這樣使用，除非這樣編寫能讓文件可讀性增加。YAML的許多擴展在JSON是找不到的，如：進階資料形態、關係錨點、字串不需要雙引號、映射資料形態會儲存鍵值的順序。 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。 --- example: > HTML goes into YAML without modification message: | <blockquote style="font: italic 12pt Times"> <p>"Three is always greater than two, even for large values of two"</p> <p>--Author Unknown</p> </blockquote> 相反的，要將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將縮排視為一個單一的空白，這可能會取得比其他標記語言更好的壓縮比。此外，極深的縮排可以完全避免的是： (1)使用“內置格式”（即簡稱類JSON格式）而無縮排；或 (2)使用關聯錨點展開階層以形成一個攤平的格式，使得YAML解析器能透明地重組成完整的數據結構。 YAML是純粹用來表達資料的語言，所以內部不會存代碼注射的可執行命令。這代表剖析器會相當（至少）安全的解析文件，而不用擔心潛在與執行命令相關的安全漏洞。舉例來說，JSON是JavaScript的子集，因此可能有人想使用JavaScript本身的剖析器直接eval，不過这样一来就造成許多代碼注射的漏洞。雖然在所有資料序列語言中，安全解析本質上是可能的，但可執行性卻正是這樣一個惡名昭彰的缺陷；而YAML缺乏相關的命令語言，可能是一個相對安全的利益。 XML和YAML規範提供非常不同的邏輯模型來進行資料結點的展現、處理及儲存。 簡單的YAML檔案（例如：簡單的鍵值對）不需要完整的YAML剖析器，便可以被正則表達式解析。許多常用的程式語言──純用某個語言，讓函式庫具有可攜性──都有的YAML的產生器和剖析器。當效能比較重要時，也有許多和C語言綁定的函式庫可使用。 libYAML 2007-06時，這個YAML的函式庫漸趨穩定，並被YAML格式作者推薦。 SYCK 這個實現支援大部分1.0版的格式，並且被廣泛的使用。它使用高階解釋型語言進行最佳化。在2005之後，這個專案已經不再更新，不過仍可使用。 下面幾種程式語言都有與YAML相關的函式庫: C++ 用C++將libYaml包裝 Go go-yaml 借鉴 C 库 libyaml 设计的 Go 语言移植。 Haskell Haskell Reference wrappers Java jvyaml 以Syck為基礎設計。 JYaml 純Java的實現。 JavaScript 原生的JavaScript即可產生YAML，但不能解析。 YAML JavaScript 同時支持產生和解析。 Objective-C Cocoa-Syck OCaml OCaml-Syck Lua Lua-Syck Perl CPAN 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 具有完全的UTF-8支持 R CRAN YAML 以SYCK為基礎。 .NET .NET Parser YamlDotNet Scala scala-yaml Tcl 在Tcl 8.4中可用 XML YAXML (當前仍在設計中) 編輯器： 建議使用能將跳格字元自動轉換成空白字元的編輯器，並且使用定寬度的字型。 編輯器要能正確的處理UTF-8和UTF16編碼（或是使用純ASCII編碼──它同時是UTF-8的子集）. 字串： YAML的字串不需使用引號，這可以增加可讀性，並避免巢狀的跳脫字元。然而，這有時也會導致錯誤，例如，字串本身是一個曖昧的字眼（像數字或布林值）；或在短句中意外的出現YAML的結構符號（常見的例子是由驚嘆號起始的句子，或是包含冒號-空白的句子："!Caca de vaca!"、"Caution: lions ahead"）。這在發布YAML檔案時並不造成困擾，但在製作小型指令碼和人工編輯檔案時，這問題卻會常常出現。比較好的方法是善用區塊符號（"|" or ">"）而不要使用單行字串，來避免這種曖昧的表示方法。 預期實做的特性 其他标记語言： JSON，可以說是YAML的子集。 XML Simple Outline XML OGDL S-表达式 Plist，由NEXTSTEP改寫成的資料序列語言。 SDL 2822 （页面存档备份，存于互联网档案馆） Evans, Clark. YAML Draft 0.1. Yahoo! Tech groups(雅虎技術群組): sml-dev. 2001-05-11 [2008-08-02]. （原始内容存档于2013-09-07）.  YAML Ain't Markup Language: About. [2010-06-16]. （原始内容存档于2022-04-03）.  Yet Another Markup Language (YAML) 1.0. [2008-11-24]. （原始内容存档于2022-03-06）.  在英文原文中，將下列幾組詞彙交替使用：(清單"list"和陣列"array"), (雜湊表"hash"、字典"dictionary"、映射"mapping")和(字串"string"和純量"scalar")。在其他程式語言，這幾組字的意義未必等價。中文則統一使用相同的詞彙。 階層式(hierarchical model)對應到樹狀結構時，只會有一個固定、整體性的結果。舉例說明：用階層式來表達電影的演員名單，每個演員都只能歸類到一個電影名稱；或是每個電影只能歸類給一位演員(雖然這樣很怪)。YAML同時也允許使用關聯式資料(relational model)。 存档副本. [2013-05-15]. （原始内容存档于2008-09-14）.  yaml.org （页面存档备份，存于互联网档案馆） 小抄 （页面存档备份，存于互联网档案馆） 格式說明 （页面存档备份，存于互联网档案馆） YAML 1.2 Spec. [2008-12-01]. （原始内容存档于2008-05-16）.  這些語法非常細微且很少出現在文件中：JSON允許擴充字元集，如：UTF32；YAML在分隔符號──如引號、等號、冒號──後方需要接空白字元，而JSON不需要；一些非標準的JSON實現允許Javascript風格的的大範圍註解/*...*/。處理這種邊界情形或許需要在將其當成內置格式的YAML剖析前進行簡單的JSON前處理。 用SYCK剖析JSON. [2008-09-28]. （原始内容存档于2008-09-14）.  存在 （页面存档备份，存于互联网档案馆） XML IDREF. [2008-09-28]. （原始内容存档于2022-05-15）.  提案中的"yield"(迭代器)標籤可以允許簡單的算術運算 Extensible Markup Language (XML) 1.0 (第四版). [2007-11-04]. （原始内容存档于2020-01-10）.  Extensible Markup Language (XML) 1.1 (第二版). [2007-11-04]. （原始内容存档于2021-04-19）.  YAML Ain't Markup Language (YAML) Version 1.1. [2007-11-04]. （原始内容存档于2022-05-01）.  libYAML （页面存档备份，存于互联网档案馆） YAML的創造者Clark Evans推薦 SYCK （页面存档备份，存于互联网档案馆） 用C++將libYaml包裝[永久失效連結] go-yaml （页面存档备份，存于互联网档案馆） Haskell Reference wrappers jvyaml JYaml YAML JavaScript （页面存档备份，存于互联网档案馆） Cocoa-Syck OCaml-Syck （页面存档备份，存于互联网档案馆） Lua-Syck CPAN YAML （页面存档备份，存于互联网档案馆） YAML::Tiny （页面存档备份，存于互联网档案馆） YAML::Syck （页面存档备份，存于互联网档案馆） YAML::XS （页面存档备份，存于互联网档案馆） Spyc PHP-Syck （页面存档备份，存于互联网档案馆） sfYaml PyYaml. [2008-09-28]. （原始内容存档于2008-09-17）.  PySyck. [2022-06-03]. （原始内容存档于2021-05-11）.  Ya2YAML CRAN YAML （页面存档备份，存于互联网档案馆） YAML .NET Parser （页面存档备份，存于互联网档案馆） YamlDotNet 12.0.0. www.nuget.org. [2022-09-14]. （原始内容存档于2022-09-16） （英语）.  scala-yaml （页面存档备份，存于互联网档案馆） 在Tcl 8.4中可用 YAXML （页面存档备份，存于互联网档案馆） YAML.org （页面存档备份，存于互联网档案馆） YAML Specification （页面存档备份，存于互联网档案馆） YAML Cookbook--Equivalent data structures in YAML and Ruby YAML in Five Minutes （页面存档备份，存于互联网档案馆） YAML improves on XML （页面存档备份，存于互联网档案馆） Intro to YAML in Python YAML as a superset of JSON Kwalify Schema definition for YAML （页面存档备份，存于互联网档案馆） Lists in 5 minutes （页面存档备份，存于互联网档案馆） YAML Validator （页面存档备份，存于互联网档案馆）