Yaml入門筆記

什么是yaml
YAML是"YAML Ain't a Markup Language"(YAML不是一種置標語言)的遞歸縮寫,早先YAML的意思其實是:"Yet Another Markup Language"(另外一種置標語言)寒随,但為了強調(diào)這種語言以數(shù)據(jù)做為中心,而不是以置標語言為重點补履,而用返璞詞重新命名材蛛,YAML的官方定義很簡單,即一種人性化的數(shù)據(jù)格式定義語言鲤桥,其主要功能用途類似于XML或JSON,YAML使用空白字符和分行來分隔數(shù)據(jù)渠概,且巧妙避開各種封閉符號茶凳,如:引號嫂拴、括號等,以避免這些符號在復(fù)雜層次結(jié)構(gòu)中變得難以辨認贮喧。YAML的語法與高階語言類似筒狠,可以很簡單地表述序列(java中的list)、雜湊表(java中的map)箱沦、標量(java中的基本類型等)數(shù)據(jù)結(jié)構(gòu)辩恼,它重點強調(diào)可閱讀性。

  • 本文內(nèi)容


    image.png

YAML的設(shè)計目的

  1. 容易人類閱讀
  2. 適合表示程序語言的數(shù)據(jù)結(jié)構(gòu)
  3. 可用于不同程序間交換數(shù)據(jù)
  4. 支持泛型工具
  5. 支持串行處理谓形?
  6. 豐富的表達能力和可擴展性
  7. 易于使用

xml和yaml的代碼塊
xml代碼塊:

<site>
    <name>github</name>
    <url>https://github.com</url>
</site>
<site>
    <name>簡書</name>
    <url>http://www.reibang.com</url>
</site>

yaml代碼塊:

---
site:
    name: github
    url: https://github.com
---
site:
    name: 簡書
    url: http://www.reibang.com
---
#或者
---
site:{name:github,url:https://github.com}
---
site:{name:簡書,url:https://jianshu.com}

主要標記

  • 注釋-comment
    舉例:
# Comment Example
# Profile Of Mary
Mary:
    - name: Mary
    - age  : 19   # age property
  • 文檔(document)
# documents example
---
site:
    name: github
    url: https://github.com
---
site:
    name: 簡書
    url: http://www.reibang.com
  • 數(shù)據(jù)結(jié)構(gòu)
    YAML的設(shè)計者認為在配置文件中所要表達的數(shù)據(jù)內(nèi)容有三種類型:標量(Scalar灶伊,如字符串和整數(shù)等)、序列(Sequence寒跳,如數(shù)組)和Mapping(類似hash的key/value pair)聘萨。


    sequence.png
mapping.png

例子:我們用YAML來描述一本書:

# 《單元測試之道-c#版》描述
---  # begin of document
書名  : '單元測試之道-C#版'
出版社: '電子工業(yè)出版社'
原作者: ['Andrew Hunt', 'David Thomas']
譯者  : 
    - 陳偉柱
    - 陶文
前二章節(jié)  : 
    - 第一章: 序言
    - 第二章: 你的首個單元測試計劃
  #end document

注意:YAML推薦使用空格作為縮進,避免了在不同編輯器中對tab的表示形式不同而可能產(chǎn)生誤解童太。



YAML 與 XML

優(yōu)勢:

  • YAML的可讀性好
  • YAML和腳本語言的交互性好
  • YAML使用實現(xiàn)語言的數(shù)據(jù)類型
  • YAML有一個一致的信息模型
  • YAML易于實現(xiàn)

上面5條是XML不足的地方米辐,同時,YAML也具有XML的下列優(yōu)點:

  • YAML可以基于流來處理
  • YAML表達能力強康愤,擴展性好

YAML類似于XML的數(shù)據(jù)描述語言儡循,語法比XML簡單很多,YAML試圖用一種比XML更敏捷的方式征冷,來完成XML所完成的任務(wù)。

YAML 與 JSON

JSON的語法其實是YAML的子集誓琼,大部分的JSON文件都可以被YAML的剖析器剖析检激。雖然大部分的數(shù)據(jù)分層形式也可以使用類似JSON的格式,不過YAML并不建議這樣使用腹侣,除非這樣編寫能讓文件可讀性增加叔收,更重要的是,YAML的許多擴展在JSON是找不到的傲隶,如:進階資料形態(tài)饺律、關(guān)系錨點字串不需要引號跺株、映射資料形態(tài)會儲存鍵值的順序等复濒。

YAML用途

腳本語言

由于實現(xiàn)簡單,解析成本很低乒省,YAML特別適合在腳本語言中使用巧颈。列一下現(xiàn)有的語言實現(xiàn):Ruby,Java袖扛,Perl砸泛,Python十籍,PHP,OCaml唇礁,JavaScript勾栗,除了Java,其他都是腳本語言盏筐。

序列化

YAML比較適合做序列化械姻。因為它是宿主語言數(shù)據(jù)類型直轉(zhuǎn)的。

配置文件

YAML做配置文件也不錯机断。寫YAML要比寫XML快得多(無需關(guān)注標簽或引號)楷拳,并且比ini文檔功能更強。

調(diào)試

由于其很強的閱讀性吏奸,用于調(diào)試過程中dump出信息供分析也是一種比較方便的做法欢揖。

YAML缺陷與不足

YAML沒有自己的數(shù)據(jù)類型的定義,而是使用實現(xiàn)語言的數(shù)據(jù)類型奋蔚。一個YAML文件她混,在不同語言中解析后得到的數(shù)據(jù)類型可能會不同,由于其兼容性問題泊碑,不同語言間的數(shù)據(jù)流轉(zhuǎn)不建議使用YAML坤按。

YAML語法與范例

  • YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16
  • 使用空白字符(不能使用<kbd>Tab</kbd>)分層馒过,同層元素左側(cè)對齊
  • 單行注解由井字號(<kbd> #</kbd> )開始臭脓,可以出現(xiàn)在行中任何位置
  • 每個清單成員以單行表示,并用短杠+空白(<kbd>- </kbd>)起始
  • 每個雜湊表的成員用冒號+空白(<kbd>: </kbd>)分開鍵和值
  • 雜湊表的鍵值可以用問號 (<kbd>?</kbd>)起始腹忽,表示多個詞匯組成的鍵值
  • 字串一般不使用引號来累,但必要的時候可以用引號框住
  • 使用雙引號表示字串時,可用倒斜線(<kbd></kbd>)進行特殊字符轉(zhuǎn)義
  • 區(qū)塊的字串用縮排和修飾詞(非必要)來和其他資料分隔窘奏,有新行保留(使用符號<kbd>|</kbd>)或新行折疊(使用符號<kbd>></kbd>)兩種方式
  • 在單一檔案中嘹锁,可用連續(xù)三個連字號(<kbd>---</kbd>)區(qū)分多個檔案
  • 可選擇性的連續(xù)三個點號(<kbd>...</kbd>)用來表示檔案結(jié)尾(在流式傳輸時非常有用,不需要關(guān)閉流即可知道到達結(jié)尾處)
  • 重復(fù)的內(nèi)容可使從參考標記星號 (<kbd>*</kbd>)復(fù)制到錨點標記(<kbd>&</kbd>)
  • 指定格式可以使用兩個驚嘆號 ( !! )着裹,后面接上名稱
receipt:     Oz-Ware Purchase Invoice
date:        2007-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 
      price:     100.27
      quantity:  1
bill-to:  &id001
    street: | 
            123 Tornado Alley
            Suite 16
    city:   East Westville
    state:  KS
ship-to:  *id001   
specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the 
    man behind the curtain.
...

這個文件的的頂層由七個鍵值組成:其中一個鍵值"items"领猾,是個兩個元素構(gòu)成的清單,清單中的兩個元素同時也是包含了四個鍵值的雜湊表骇扇。
文件中重復(fù)的部分處理方式:使用錨點(&)和參考(*)標簽將"bill-to"雜湊表的內(nèi)容復(fù)制到"ship-to"雜湊表摔竿。也可以在文件中加入選擇性的空行,以增加可讀性匠题。

YAML的JAVA實現(xiàn)

YAML已經(jīng)有了多種語言不少實現(xiàn)拯坟,詳見YAML官網(wǎng)
一般YAML文件擴展名為.yaml韭山,比如John.yaml郁季,其內(nèi)容為:

name: John Smith
age: 37
children:
    - name: Jimmy Smith
      age: 15
    - name: Jenny Smith
      age: 12
spouse:
    name: Jane Smith
    age: 25

由于yaml的超強可讀性冷溃,我們了解到:John今年37歲,兩個孩子Jimmy 和Jenny活潑可愛梦裂,妻子Jane年輕美貌似枕,而且年僅25歲,一個幸福的四口之家年柠。
對John.yaml進行java描述凿歼,抽象出一個Person類,如下:

public class Person {
    private String name;
    private int age;
    private Person sponse;
    private Person[] children;
    // setXXX, getXXX方法略.
}

現(xiàn)在我們使用java裝配一個Jone:

    Person john = new Person();
    john.setAge(37);
    john.setName("John Smith");
    Person sponse = new Person();
    sponse.setName("Jane Smith");
    sponse.setAge(25);
    john.setSponse(sponse);
    Person[] children = {new Person(), new Person()};
    children[0].setName("Jimmy Smith");
    children[0].setAge(15);
    children[1].setName("Jenny Smith");
    children[1].setAge(12);
    john.setChildren(children);

使用SnakeYAML實現(xiàn)

項目主頁:http://code.google.com/p/snakeyaml/
使用手冊:https://code.google.com/p/snakeyaml/wiki/Documentation
SnakeYAML是一個標準的YAML的java實現(xiàn)冗恨,它有以下特點:

  • 完全支持YAML 1.1答憔,可以跑通規(guī)范中的所有示例
  • 支持YAML的所有類型
  • 支持UTF-8/UTF-16的輸入和輸出
  • 提供了本地java對象的序列化和反序列化的高層API
  • 提供相對合理的錯誤提示信息

使用SnakeYAML將john dump出來,如果有引用相同對象掀抹,則dump出到y(tǒng)aml文件會自動使用<kbd>&</kbd>和<kbd></kbd>進行錨點和引用*:

DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
//Yaml yaml = new Yaml();
String dump = yaml.dump(john);
System.out.println(dump);

內(nèi)容如下:

!!Person
age: 37
children:
- age: 15
  children: null
  name: Jimmy Smith
  sponse: null
- age: 12
  children: null
  name: Jenny Smith
  sponse: null
name: John Smith
sponse:
  age: 25
  children: null
  name: Jane Smith
  sponse: null

現(xiàn)在用SnakeYAML把yaml load進來虐拓,如果yaml文件中使用了<kbd>&</kbd>和<kbd></kbd>,則會自動對load出來的對象賦相同的值*:

Yaml yaml = new Yaml();
Object load = yaml.load(new FileInputStream(new File("jhon.yaml")));
System.out.println(load.getClass());
System.out.println(yaml.dump(load));

Yaml yaml = new Yaml(options);
Person person = yaml.loadAs(inputStream, Person.class);
System.out.println(person.getSponse().getChildren().length);

如果一個yaml文件中有多個文檔傲武,由<kbd>---</kbd>分割蓉驹,解析如下:

Yaml yaml = new Yaml();
        int counter = 0;
        for (Object data : yaml.loadAll(input)) {
            System.out.println(data);
            counter++;
        }

保存一個Map對象:

Map<String, Object> data = new HashMap<String, Object>();
        data.put("name", "Silenthand Olleander");
        data.put("race", "Human");
        data.put("traits", new String[] { "ONE_HAND", "ONE_EYE" });
        Yaml yaml = new Yaml();
        String output = yaml.dump(data);
        System.out.println(output);
    // or
    StringWriter writer = new StringWriter();
    yaml.dump(data, writer);
    System.out.println(writer.toString());

將多個文檔dump出到同一個yaml文件中去:

List<Integer> docs = new LinkedList<Integer>();
    for (int i = 1; i < 4; i++) {
        docs.add(i);
    }
    DumperOptions options = new DumperOptions();
    //options.setCanonical(true);
    options.explicitStart(true);
    Yaml yaml = new Yaml(options);
    System.out.println(yaml.dump(docs));
    System.out.println(yaml.dumpAll(docs.iterator()));
--- [1, 2, 3]

--- 1
--- 2
--- 3
YAML JAVA
!null null
!!bool Boolean
!!int Integer, Long, BigInteger
!!float Double
!!binary String
!!timestamp java.util.Date, java.sql.Date, java.sql.Timestamp
!!omap, !!pairs List of Object[]
!!set Set
!!str String
!!seq List
!!map Map

YAML與java類型對照表:

YAML JAVA
!null null
!!bool Boolean
!!int Integer, Long, BigInteger
!!float Double
!!binary String
!!timestamp java.util.Date, java.sql.Date, java.sql.Timestamp
!!omap, !!pairs List of Object[]
!!set Set
!!str String
!!seq List
!!map Map

集合的默認實現(xiàn)是:

  • List: ArrayList
  • Map: LinkedHashMap

使用JYaml實現(xiàn)

JYaml(最新版本是2007年的,可以考慮放棄了)揪利,使用JYaml把Jone “Dump” 出來:

    File dumpfile = new File("John_dump.yaml");
    Yaml.dump(john, dumpfile);

下面我們看看John_dump.yaml是什么樣子:

--- !yaml.test.internal.Person
age: 37
children: !yaml.test.internal.Person[]
  - !yaml.test.internal.Person
    age: 15
    name: Jimmy Smith
  - !yaml.test.internal.Person
    age: 12
    name: Jenny Smith
name: John Smith
sponse: !yaml.test.internal.Person
  age: 25
  name: Jane Smith

其中!yaml.test.internal.Person是一些類型的信息态兴。load的時候需要用。
現(xiàn)在用JYaml把Jone_dump.yaml load進來:

    Person john2 = (Person) Yaml.loadType(dumpfile, Person.class);

還可以用下面的代碼dump出沒有類型信息的John.yaml:

Yaml.dump(john,dumpfile, true);

我們再來看看JYaml對流處理的支持疟位,為簡便起見瞻润,我們只是把同一個john寫10次:

    YamlEncoder enc = new YamlEncoder(new FileOutputStream(dumpfile));
    for(int i=0; i<10; i++){
        john.setAge(37+i);
        enc.writeObject(john);
        enc.flush();
    }
   enc.close();

下面再把這十個對象一個一個讀出來(注意while循環(huán)退出的方式):

   YamlDecoder dec = new YamlDecoder(new FileInputStream(dumpfile));
   int age = 37;
   while(true){
       try{
           john = (Person) dec.readObject();
           assertEquals(age, john.getAge());
           age++;
       }catch(EOFException eofe){
           break;
       }
   }

參考文檔:

YAML Specification

YAML 數(shù)據(jù)類型說明

http://blog.csdn.net/conquer0715/article/details/42108061

http://www.cnblogs.com/chwkai/archive/2009/03/01/249924.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市献汗,隨后出現(xiàn)的幾起案子敢订,更是在濱河造成了極大的恐慌,老刑警劉巖罢吃,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昭齐,居然都是意外死亡尿招,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門阱驾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來就谜,“玉大人,你說我怎么就攤上這事里覆∩ゼ觯” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵喧枷,是天一觀的道長虹统。 經(jīng)常有香客問我弓坞,道長,這世上最難降的妖魔是什么车荔? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任渡冻,我火速辦了婚禮,結(jié)果婚禮上忧便,老公的妹妹穿的比我還像新娘族吻。我一直安慰自己,他們只是感情好珠增,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布超歌。 她就那樣靜靜地躺著,像睡著了一般蒂教。 火紅的嫁衣襯著肌膚如雪巍举。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天悴品,我揣著相機與錄音谨设,去河邊找鬼。 笑死桦沉,一個胖子當著我的面吹牛蟀瞧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播届氢,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼欠窒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了退子?” 一聲冷哼從身側(cè)響起岖妄,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寂祥,沒想到半個月后荐虐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡丸凭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年福扬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惜犀。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡铛碑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出虽界,到底是詐尸還是另有隱情汽烦,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布莉御,位于F島的核電站撇吞,受9級特大地震影響俗冻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梢夯,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一言疗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颂砸,春花似錦噪奄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至色罚,卻和暖如春碰缔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戳护。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工金抡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腌且。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓梗肝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铺董。 傳聞我的和親對象是個殘疾皇子巫击,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容