YAML预研文档

YAML概要

YAML是”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优越性表现在

优势:

  • YAML的可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现

上面5条是XML不足的地方,同时,YAML也具有XML的下列优点:

  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

YAML类似于XML的数据描述语言,语法比XML简单很多,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。


YAML vs JSON

JSON的语法其实是YAML的子集,大部分的JSON文件都可以被YAML的剖析器剖析。虽然大部分的数据分层形式也可以使用类似JSON的格式,不过YAML并不建议这样使用,除非这样编写能让文件可读性增加,更重要的是,YAML的许多扩展在JSON是找不到的,如:进阶资料形态关系锚点字串不需要引号映射资料形态会储存键值的顺序等。

YAML用途

脚本语言

由于实现简单,解析成本很低,YAML特别适合在脚本语言中使用。列一下现有的语言实现:Ruby,Java,Perl,PythonPHP,OCaml,JavaScript,除了Java,其他都是脚本语言。

序列化

YAML比较适合做序列化。因为它是宿主语言数据类型直转的。

配置文件

YAML做配置文件也不错。写YAML要比写XML快得多(无需关注标签或引号),并且比ini文档功能更强。

调试

由于其很强的阅读性,用于调试过程中dump出信息供分析也是一种比较方便的做法。

YAML缺陷与不足

YAML没有自己的数据类型的定义,而是使用实现语言的数据类型。一个YAML文件,在不同语言中解析后得到的数据类型可能会不同,由于其兼容性问题,不同语言间的数据流转不建议使用YAML。

YAML语法与范例

  • YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16
  • 使用空白字符(不能使用Tab)分层,同层元素左侧对齐
  • 单行注解由井字号( # )开始,可以出现在行中任何位置
  • 每个清单成员以单行表示,并用短杠+空白(- )起始
  • 每个杂凑表的成员用冒号+空白(: )分开键和值
  • 杂凑表的键值可以用问号 (?)起始,表示多个词汇组成的键值
  • 字串一般不使用引号,但必要的时候可以用引号框住
  • 使用双引号表示字串时,可用倒斜线(\)进行特殊字符转义
  • 区块的字串用缩排和修饰词(非必要)来和其他资料分隔,有新行保留(使用符号|)或新行折叠(使用符号>)两种方式
  • 在单一档案中,可用连续三个连字号(---)区分多个档案
  • 可选择性的连续三个点号(...)用来表示档案结尾(在流式传输时非常有用,不需要关闭流即可知道到达结尾处)
  • 重复的内容可使从参考标记星号 (*)复制到锚点标记(&)
  • 指定格式可以使用两个惊叹号 ( !! ),后面接上名称
  1. receipt: Oz-Ware Purchase Invoice
  2. date: 2007-08-06
  3. customer:
  4. given: Dorothy
  5. family: Gale
  6. items:
  7. - part_no: A4786
  8. descrip: Water Bucket (Filled)
  9. price: 1.47
  10. quantity: 4
  11. - part_no: E1628
  12. descrip: High Heeled "Ruby" Slippers
  13. price: 100.27
  14. quantity: 1
  15. bill-to: &id001
  16. street: |
  17. 123 Tornado Alley
  18. Suite 16
  19. city: East Westville
  20. state: KS
  21. ship-to: *id001
  22. specialDelivery: >
  23. Follow the Yellow Brick
  24. Road to the Emerald City.
  25. Pay no attention to the
  26. man behind the curtain.
  27. ...

这个文件的的顶层由七个键值组成:其中一个键值”items”,是个两个元素构成的清单,清单中的两个元素同时也是包含了四个键值的杂凑表。 
文件中重复的部分处理方式:使用锚点(&)和参考(*)标签将”bill-to”杂凑表的内容复制到”ship-to”杂凑表。也可以在文件中加入选择性的空行,以增加可读性。

YAML的JAVA实现

YAML已经有了多种语言不少实现,详见YAML官网。 
一般YAML文件扩展名为.yaml,比如John.yaml,其内容为:

  1. name: John Smith
  2. age: 37
  3. children:
  4. - name: Jimmy Smith
  5. age: 15
  6. - name: Jenny Smith
  7. age: 12
  8. spouse:
  9. name: Jane Smith
  10. age: 25

由于yaml的超强可读性,我们了解到:John今年37岁,两个孩子Jimmy 和Jenny活泼可爱,妻子Jane年轻美貌,而且年仅25岁,一个幸福的四口之家。 
对John.yaml进行java描述,抽象出一个Person类,如下:

  1. public class Person {
  2. private String name;
  3. private int age;
  4. private Person sponse;
  5. private Person[] children;
  6. // setXXX, getXXX方法略.
  7. }

现在我们使用java装配一个Jone:

  1. Person john = new Person();
  2. john.setAge(37);
  3. john.setName("John Smith");
  4. Person sponse = new Person();
  5. sponse.setName("Jane Smith");
  6. sponse.setAge(25);
  7. john.setSponse(sponse);
  8. Person[] children = {new Person(), new Person()};
  9. children[0].setName("Jimmy Smith");
  10. children[0].setAge(15);
  11. children[1].setName("Jenny Smith");
  12. children[1].setAge(12);
  13. john.setChildren(children);

使用SnakeYAML实现

项目主页:http://code.google.com/p/snakeyaml/ 
使用手册:https://code.google.com/p/snakeyaml/wiki/Documentation 
SnakeYAML是一个标准的YAML的java实现,它有以下特点:

  • 完全支持YAML 1.1,可以跑通规范中的所有示例
  • 支持YAML的所有类型
  • 支持UTF-8/UTF-16的输入和输出
  • 提供了本地java对象的序列化和反序列化的高层API
  • 提供相对合理的错误提示信息

使用SnakeYAML将john dump出来,如果有引用相同对象,则dump出到yaml文件会自动使用&和*进行锚点和引用

  1. DumperOptions options = new DumperOptions();
  2. options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
  3. Yaml yaml = new Yaml(options);
  4. //Yaml yaml = new Yaml();
  5. String dump = yaml.dump(john);
  6. System.out.println(dump);

内容如下:

  1. !!Person
  2. age: 37
  3. children:
  4. - age: 15
  5. children: null
  6. name: Jimmy Smith
  7. sponse: null
  8. - age: 12
  9. children: null
  10. name: Jenny Smith
  11. sponse: null
  12. name: John Smith
  13. sponse:
  14. age: 25
  15. children: null
  16. name: Jane Smith
  17. sponse: null

现在用SnakeYAML把yaml load进来,如果yaml文件中使用了&和*,则会自动对load出来的对象赋相同的值

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

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

如果一个yaml文件中有多个文档,由---分割,解析如下:

  1. Yaml yaml = new Yaml();
  2. int counter = 0;
  3. for (Object data : yaml.loadAll(input)) {
  4. System.out.println(data);
  5. counter++;
  6. }

保存一个Map对象:

  1. Map<String, Object> data = new HashMap<String, Object>();
  2. data.put("name", "Silenthand Olleander");
  3. data.put("race", "Human");
  4. data.put("traits", new String[] { "ONE_HAND", "ONE_EYE" });
  5. Yaml yaml = new Yaml();
  6. String output = yaml.dump(data);
  7. System.out.println(output);
  8. // or
  9. StringWriter writer = new StringWriter();
  10. yaml.dump(data, writer);
  11. System.out.println(writer.toString());

将多个文档dump出到同一个yaml文件中去:

  1. List<Integer> docs = new LinkedList<Integer>();
  2. for (int i = 1; i < 4; i++) {
  3. docs.add(i);
  4. }
  5. DumperOptions options = new DumperOptions();
  6. //options.setCanonical(true);
  7. options.explicitStart(true);
  8. Yaml yaml = new Yaml(options);
  9. System.out.println(yaml.dump(docs));
  10. System.out.println(yaml.dumpAll(docs.iterator()));
  1. --- [1, 2, 3]
  2. --- 1
  3. --- 2
  4. --- 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” 出来:

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

下面我们看看John_dump.yaml是什么样子:

  1. --- !yaml.test.internal.Person
  2. age: 37
  3. children: !yaml.test.internal.Person[]
  4. - !yaml.test.internal.Person
  5. age: 15
  6. name: Jimmy Smith
  7. - !yaml.test.internal.Person
  8. age: 12
  9. name: Jenny Smith
  10. name: John Smith
  11. sponse: !yaml.test.internal.Person
  12. age: 25
  13. name: Jane Smith

其中!yaml.test.internal.Person是一些类型的信息。load的时候需要用。 
现在用JYaml把Jone_dump.yaml load进来:

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

还可以用下面的代码dump出没有类型信息的John.yaml:

  1. Yaml.dump(john,dumpfile, true);

我们再来看看JYaml对流处理的支持,为简便起见,我们只是把同一个john写10次:

  1. YamlEncoder enc = new YamlEncoder(new FileOutputStream(dumpfile));
  2. for(int i=0; i<10; i++){
  3. john.setAge(37+i);
  4. enc.writeObject(john);
  5. enc.flush();
  6. }
  7. enc.close();

下面再把这十个对象一个一个读出来(注意while循环退出的方式):

  1. YamlDecoder dec = new YamlDecoder(new FileInputStream(dumpfile));
  2. int age = 37;
  3. while(true){
  4. try{
  5. john = (Person) dec.readObject();
  6. assertEquals(age, john.getAge());
  7. age++;
  8. }catch(EOFException eofe){
  9. break;
  10. }
  11. }

YAML 技术研究的更多相关文章

  1. <脱机手写汉字识别若干关键技术研究>

    脱机手写汉字识别若干关键技术研究 对于大字符集识别问题,一般采用模板匹配的算法,主要是因为该算法比较简单,识别速度快.但直接的模板匹配算法往往无法满足实际应用中对识别精度的需求.为此任俊玲编著的< ...

  2. 重复数据删除(De-duplication)技术研究(SourceForge上发布dedup util)

    dedup util是一款开源的轻量级文件打包工具,它基于块级的重复数据删除技术,可以有效缩减数据容量,节省用户存储空间.目前已经在Sourceforge上创建项目,并且源码正在不断更新中.该工具生成 ...

  3. 伪AP检测技术研究

    转载自:http://www.whitecell-club.org/?p=310 随着城市无线局域网热点在公共场所大规模的部署,无线局域网安全变得尤为突出和重要,其中伪AP钓鱼攻击是无线网络中严重的安 ...

  4. Azure IoT 技术研究系列2-起步示例之设备注册到Azure IoT Hub

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  5. Azure IoT 技术研究系列3-设备到云、云到设备通信

    上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...

  6. Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别

    上两篇博文中,我们介绍了将设备注册到Azure IoT Hub,设备到云.云到设备之间的通信: Azure IoT 技术研究系列2-设备注册到Azure IoT Hub Azure IoT 技术研究系 ...

  7. Azure IoT 技术研究系列5-Azure IoT Hub与Event Hub比较

    上篇博文中,我们介绍了Azure IoT Hub的使用配额和缩放级别: Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别 本文中,我们比较一下Azure IoT Hub和 ...

  8. Azure Event Hub 技术研究系列2-发送事件到Event Hub

    上篇博文中,我们介绍了Azure Event Hub的一些基本概念和架构: Azure Event Hub 技术研究系列1-Event Hub入门篇 本篇文章中,我们继续深入研究,了解Azure Ev ...

  9. Azure Event Hub 技术研究系列3-Event Hub接收事件

    上篇博文中,我们通过编程的方式介绍了如何将事件消息发送到Azure Event Hub: Azure Event Hub 技术研究系列2-发送事件到Event Hub 本篇文章中,我们继续:从Even ...

随机推荐

  1. bbs/贴吧/盖楼的技术实现(PHP)

    2015年3月5日 14:36:44 更新: 2015年7月18日 16:33:23 星期六 目标, 实现类似网易盖楼的功能, 但是不重复显示帖子 效果: * 回复 //1楼 ** 回复 //1楼的子 ...

  2. 使用php脚本查看已开启的扩展

    php安装时会将扩展包编译进去,对于一个正在运行中的数据库,查看php的扩展开启状况,第一种方式是通过配置文件查看,另外是通过phpinfo函数查看所有的配置,另外是使用php内置函数来查看,通过脚本 ...

  3. 100m和1000m网线的常见制作方法

    100m和1000m网线的常见制作方法 100m和1000m网线的常见制作方法: 5类线(100m)的制作: a: 绿白(3).绿(6).橙白(1).蓝(4).蓝白(5).橙(2).棕白(7).棕(8 ...

  4. FastReport经验

    FastReport经验 1.FastReport中如果访问报表中的对象? 可以使用FindObject方法. TfrxMemoView(frxReport1.FindObject(’memo1′)) ...

  5. SSM 加载配置文件

    配置文件中 <bean id="address" class="org.springframework.beans.factory.config.Propertie ...

  6. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。

    前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...

  7. 原始套接字SOCK_RAW

    原始套接字SOCK_RAW 实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包 ...

  8. CSS3混合模式background-blend-mode

    注意:background属性中的背景图片和颜色混合,只能在一个background属性中. 属性值: background-blend-mode: normal; //正常 background-b ...

  9. android setCompoundDrawables 不显示问题

    在 vh.tvAddr.setCompoundDrawables(getResources().getDrawable(R.drawable.ic_real_state_loc), null, nul ...

  10. codevs 2530大质数

    链接:http://codevs.cn/problem/1530/ 解题思路: 这个题最关键的剪枝还是 因子小于平方根,但不是像原来那样用. 逆转思维,与其说判断哪些是质数,不如说判断哪些不是质数,更 ...