【Yaml】Yaml学习笔记
轉載:https://blog.csdn.net/moshenglv/article/details/52084899
YAML何許物也?在XML泛濫的情況下,YAML的出現的確讓人眼前一亮,在初步學習了YAML以后,粗略的總結了一下,拿出來和大家分享。
[MindMap]
[參考文檔]
YAML Specification?
YAML 數據類型說明
[摘要]
YAML的設計目的
YAML描述: [注釋, 文檔, 數據結構, 數據類型, 其他]
?
YAML的設計目的
1、容易人類閱讀
2、適合表示程序語言的數據結構
3、可用于不同程序間交換數據
4、支持泛型工具
5、支持串行處理?
6、豐富的表達能力和可擴展性
7、易于使用
粗看了specification以后感覺最好的是“容易人類閱讀”,對比一下下面的xml和yaml的代碼塊:
# xml代碼塊:
????<name>sina</name>
????<url>http://www.sina.com.cn</url>?
</site>
<site>
????<name>google</name>
????<url>http://www.google.com</url>
</site>
# YAML代碼塊
site:?
????name:?sina?
????url?:?http://www.sina.com.cn
---
site:
????name:?google
????url?:?http://www.google.com
或:
---site:?{name:?sina,?url:?http://www.sina.com.cn}
---
site:?{name:?google,?url:?http://www.google.com}
YAML利用縮進或者是explicit indicatior(如上面的{})來表示屬性的嵌套,更為直觀和simple。
?
YAML描述
“YAML?Ain't?Markup?Language”?(abbreviated?YAML)?is?a?data?serialization?language?designed?to?be?human-friendly?and work?well?with?modern?programming?languages?for?common?everyday?tasks.
先來看看YAML里的主要標記:
(1)注釋:
舉個例子:
# Comment Example
# Profile Of Mary
Mary:
??? - name: Mary
??? - age? : 19?? # age property
(2)文檔(document):
現在還不明白文檔是什么意思,既然YAML定義是data serialization,暫時把一個doucment視為一個object序列化后得到的yaml配置信息
??? ---
site:?{name:?sina,?url:?http://www.sina.com.cn}
---
site:?{name:?google,?url:?http://www.google.com}
(3)數據結構:
YAML的設計者認為在配置文件中所要表達的數據內容有三種類型:標量(Scalar,如字符串和整數等)、序列(Sequence,如數組)和Mapping(類似hash的key/value pair)。
sequence型主要是用來表示數組類型的數據。下圖描述了YAML中Sequence型數據的表示法:
mapping數據類型主要用來表示key: value對類型的數據。YAML描述方式見下圖:
最后,我們用YAML來描述一本書《單元測試知道-c#版》
---??#?begin?of?document
書名??:?'單元測試之道-C#版'
出版社:?'電子工業(yè)出版社'
原作者:?['Andrew?Hunt',?'David?Thomas']
譯者??:?
????-?陳偉柱
?????-?陶文
前二章節(jié)??:?
????-?第一章:?序言
????-?第二章:?你的首個單元測試計劃
??#end?of?document
YAML推薦使用空格作為縮進,避免了在不同編輯器中對tab的表示形式不同而可能產生誤解。
=============================================================================================================
[TOC]
#YAML預研文檔
##YAML概要
[YAML](http://yaml.org/)是"YAML Ain't a Markup Language"(YAML不是一種置標語言)的遞歸縮寫,早先YAML的意思其實是:"Yet Another Markup Language"(另外一種置標語言),但為了強調這種語言以數據做為中心,而不是以置標語言為重點,而用返璞詞重新命名,YAML的官方定義很簡單,即**一種人性化的數據格式定義語言**,其主要功能用途類似于XML或JSON,YAML使用空白字符和分行來分隔數據,且巧妙避開各種封閉符號,如:引號、括號等,以避免這些符號在復雜層次結構中變得難以辨認。YAML的語法與高階語言類似,可以很簡單地表述*序列(java中的list)、雜湊表(java中的map)、標量(java中的基本類型等)*數據結構,它重點強調可閱讀性。
##YAML vs XML
與YAML相似的數據格式定義語言是XML,YAML比XML優(yōu)越性表現在
> **優(yōu)勢:**
> -? YAML的可讀性好
> - YAML和腳本語言的交互性好
> - YAML使用實現語言的數據類型
> - YAML有一個一致的信息模型
> - YAML易于實現
上面5條是XML不足的地方,同時,YAML也具有XML的下列優(yōu)點:
> - YAML可以基于流來處理
> - YAML表達能力強,擴展性好
YAML類似于XML的數據描述語言,語法比XML簡單很多,YAML試圖用一種比XML更敏捷的方式,來完成XML所完成的任務。
----------
##YAML vs JSON
JSON的語法其實是YAML的子集,大部分的JSON文件都可以被YAML的剖析器剖析。雖然大部分的數據分層形式也可以使用類似JSON的格式,不過YAML并不建議這樣使用,除非這樣編寫能讓文件可讀性增加,更重要的是,YAML的許多擴展在JSON是找不到的,如:*進階資料形態(tài)*、*關系錨點*、*字串不需要引號*、*映射資料形態(tài)會儲存鍵值的順序*等。
##YAML用途
###腳本語言
由于實現簡單,解析成本很低,YAML特別適合在腳本語言中使用。列一下現有的語言實現:Ruby,Java,Perl,Python,PHP,OCaml,JavaScript,除了Java,其他都是腳本語言。
###序列化
YAML比較適合做序列化。因為它是宿主語言數據類型直轉的。
###配置文件
YAML做配置文件也不錯。寫YAML要比寫XML快得多(**無需關注標簽或引號**),并且比ini文檔功能更強。
###調試
由于其很強的閱讀性,用于調試過程中dump出信息供分析也是一種比較方便的做法。
##YAML缺陷與不足
YAML沒有自己的數據類型的定義,而是使用實現語言的數據類型。一個YAML文件,在不同語言中解析后得到的數據類型可能會不同,由于其兼容性問題,不同語言間的數據流轉不建議使用YAML。
##YAML語法與范例
> - YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16
> - 使用**空白字符**(不能使用<kbd>Tab</kbd>)分層,同層元素左側對齊
> - 單行注解由井字號(<kbd> #</kbd> )開始,可以出現在行中任何位置
> - 每個清單成員以單行表示,并用短杠+空白(<kbd>-? </kbd>)起始
> - 每個雜湊表的成員用冒號+空白(<kbd>:? </kbd>)分開鍵和值
> - 雜湊表的鍵值可以用問號 (<kbd>?</kbd>)起始,表示多個詞匯組成的鍵值
> - 字串一般不使用引號,但必要的時候可以用引號框住
> - 使用雙引號表示字串時,可用倒斜線(<kbd>\</kbd>)進行特殊字符轉義
> - 區(qū)塊的字串用縮排和修飾詞(非必要)來和其他資料分隔,有新行保留(使用符號<kbd>|</kbd>)或新行折疊(使用符號<kbd>></kbd>)兩種方式
> - 在單一檔案中,可用連續(xù)三個連字號(<kbd>---</kbd>)區(qū)分多個檔案
> - 可選擇性的連續(xù)三個點號(<kbd>...</kbd>)用來表示檔案結尾(在流式傳輸時非常有用,不需要關閉流即可知道到達結尾處)
> - 重復的內容可使從參考標記星號 (<kbd>*</kbd>)復制到錨點標記(<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",是個兩個元素構成的清單,清單中的兩個元素同時也是包含了四個鍵值的雜湊表。
文件中重復的部分處理方式:使用錨點(&)和參考(*)標簽將"bill-to"雜湊表的內容復制到"ship-to"雜湊表。也可以在文件中加入選擇性的空行,以增加可讀性。
##YAML的JAVA實現
YAML已經有了多種語言不少實現,詳見[YAML官網](http://yaml.org/)。
一般YAML文件擴展名為.yaml,比如John.yaml,其內容為:
```
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方法略.
}
```
現在我們使用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實現
項目主頁:http://code.google.com/p/snakeyaml/
使用手冊:https://code.google.com/p/snakeyaml/wiki/Documentation
SnakeYAML是一個標準的YAML的java實現,它有以下特點:
> - 完全支持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);
```
內容如下:
```
!!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
```
現在用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類型對照表:
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
集合的默認實現是:
> - List: ?ArrayList
> - Map: ?LinkedHashMap
###使用JYaml實現
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的時候需要用。
現在用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;
?????? }
?? }
```
轉載于:https://www.cnblogs.com/ceshi2016/p/9639668.html
總結
以上是生活随笔為你收集整理的【Yaml】Yaml学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目成本管理(二)
- 下一篇: windows下如何访问linux下的o