YAML 技术研究
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,Python,PHP,OCaml,JavaScript,除了Java,其他都是脚本语言。
序列化
YAML比较适合做序列化。因为它是宿主语言数据类型直转的。
配置文件
YAML做配置文件也不错。写YAML要比写XML快得多(无需关注标签或引号),并且比ini文档功能更强。
调试
由于其很强的阅读性,用于调试过程中dump出信息供分析也是一种比较方便的做法。
YAML缺陷与不足
YAML没有自己的数据类型的定义,而是使用实现语言的数据类型。一个YAML文件,在不同语言中解析后得到的数据类型可能会不同,由于其兼容性问题,不同语言间的数据流转不建议使用YAML。
YAML语法与范例
- YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16
- 使用空白字符(不能使用Tab)分层,同层元素左侧对齐
- 单行注解由井字号( # )开始,可以出现在行中任何位置
- 每个清单成员以单行表示,并用短杠+空白(- )起始
- 每个杂凑表的成员用冒号+空白(: )分开键和值
- 杂凑表的键值可以用问号 (?)起始,表示多个词汇组成的键值
- 字串一般不使用引号,但必要的时候可以用引号框住
- 使用双引号表示字串时,可用倒斜线(\)进行特殊字符转义
- 区块的字串用缩排和修饰词(非必要)来和其他资料分隔,有新行保留(使用符号|)或新行折叠(使用符号>)两种方式
- 在单一档案中,可用连续三个连字号(---)区分多个档案
- 可选择性的连续三个点号(...)用来表示档案结尾(在流式传输时非常有用,不需要关闭流即可知道到达结尾处)
- 重复的内容可使从参考标记星号 (*)复制到锚点标记(&)
- 指定格式可以使用两个惊叹号 ( !! ),后面接上名称
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官网。
一般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,可以跑通规范中的所有示例
- 支持YAML的所有类型
- 支持UTF-8/UTF-16的输入和输出
- 提供了本地java对象的序列化和反序列化的高层API
- 提供相对合理的错误提示信息
使用SnakeYAML将john dump出来,如果有引用相同对象,则dump出到yaml文件会自动使用&和*进行锚点和引用:
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文件中使用了&和*,则会自动对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文件中有多个文档,由---分割,解析如下:
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循环退出的方式):
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 技术研究的更多相关文章
- <脱机手写汉字识别若干关键技术研究>
脱机手写汉字识别若干关键技术研究 对于大字符集识别问题,一般采用模板匹配的算法,主要是因为该算法比较简单,识别速度快.但直接的模板匹配算法往往无法满足实际应用中对识别精度的需求.为此任俊玲编著的< ...
- 重复数据删除(De-duplication)技术研究(SourceForge上发布dedup util)
dedup util是一款开源的轻量级文件打包工具,它基于块级的重复数据删除技术,可以有效缩减数据容量,节省用户存储空间.目前已经在Sourceforge上创建项目,并且源码正在不断更新中.该工具生成 ...
- 伪AP检测技术研究
转载自:http://www.whitecell-club.org/?p=310 随着城市无线局域网热点在公共场所大规模的部署,无线局域网安全变得尤为突出和重要,其中伪AP钓鱼攻击是无线网络中严重的安 ...
- Azure IoT 技术研究系列2-起步示例之设备注册到Azure IoT Hub
上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...
- Azure IoT 技术研究系列3-设备到云、云到设备通信
上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...
- Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别
上两篇博文中,我们介绍了将设备注册到Azure IoT Hub,设备到云.云到设备之间的通信: Azure IoT 技术研究系列2-设备注册到Azure IoT Hub Azure IoT 技术研究系 ...
- Azure IoT 技术研究系列5-Azure IoT Hub与Event Hub比较
上篇博文中,我们介绍了Azure IoT Hub的使用配额和缩放级别: Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别 本文中,我们比较一下Azure IoT Hub和 ...
- Azure Event Hub 技术研究系列2-发送事件到Event Hub
上篇博文中,我们介绍了Azure Event Hub的一些基本概念和架构: Azure Event Hub 技术研究系列1-Event Hub入门篇 本篇文章中,我们继续深入研究,了解Azure Ev ...
- Azure Event Hub 技术研究系列3-Event Hub接收事件
上篇博文中,我们通过编程的方式介绍了如何将事件消息发送到Azure Event Hub: Azure Event Hub 技术研究系列2-发送事件到Event Hub 本篇文章中,我们继续:从Even ...
随机推荐
- (转)大数据时代下的SQL Server第三方负载均衡方案----Moebius测试
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...
- Collection、Map、数组 遍历方式
结论:无论是数组还是Collection for each 都是一个非常好的选择 一.for each底层实现 对于Collection,for each是隐式调用Iterator实现的,效率比显示调 ...
- Centos6.5 SVN服务器 搭建及配置
现有的项目开发中,版本控制机必不可少.合理的使用版本控制可以提高开发效果,在保证项目是最新的同时,也提高了源代码的安全性. 工具/原料 接入Internet的一台Centos6.5Linux计算机 安 ...
- codeforces 425D Sereja and Squares n个点构成多少个正方形
输入n个点,问可以构成多少个正方形.n,xi,yi<=100,000. 刚看题的时候感觉好像以前见过╮(╯▽╰)╭最近越来越觉得以前见过的题偶尔就出现类似的,可是以前不努力啊,没做出来的没认真研 ...
- Asp.Net之自定义表达式构造器(ExpressionBuilder)
在Asp.Net的Page页面中我们经常会使用到资源文件.读取资源文件的方式为:<%$Resources:Resource1,Test1%>,这样就可以显示Resource1这个资源文件中 ...
- Android Volley入门到精通:使用Volley加载网络图片
在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中我们即将学习关于Volley更加高级的用法,如何你还没有看过我的上一篇文章的话,建议先去阅读Android Volley完 ...
- cocos2d-x 第三篇 基本概念介绍
场景(scene): 也有人叫做屏幕或舞台,是一个独立的程序流,一个程序可以有很多场景但当前运行的场景就只有一个.比如游戏中可以有介绍场景,菜单场景,第一关场景,过场1场景,第二关场景,胜利场景等.一 ...
- 在没装VS2010的机器上运行VS2010开发的C++程序
在VS2010下写了一个win32控制台应用程序,编译ok.exe,需要依赖osg相关动态库 第一次编译的是Debug版本的,直接将ok.exe和osg相关dll文件拷贝到没有安装VS2010机器上运 ...
- 二、JavaScript语言--JS实践--倒计时效果
主要内容:分析不同倒计时效果的计算思路及方法,掌握日期对象Date,获取时间的方法,计算时差的方法,实现不同的倒时计效果. Javascript 日期对象: Date()返回当前的日期和时间 getY ...
- JS添加MD5,JS提示框
http://pan.baidu.com/s/1kTmSp9t