所有栏目

YAML

作者:爱百科

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

YAML介绍

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。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的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。尽管它比较适合用来表达层次结构式(hierarchical model)的数据结构,不过也有精致的语法可以表示关系性(relational model)的数据。由于YAML使用空白字符和分行来分隔数据,使得它特别适合用grep/Python/Perl/Ruby操作。其让人最容易上手的特色是巧妙避开各种封闭符号,如:引号、各种括号等,这些符号在嵌套结构时会变得复杂而难以辨认。

YAML示例

YAML简单的文件

数据结构可以用类似大纲的缩进方式呈现

---receipt:     Oz-Ware Purchase Invoicedate:        2012-08-06customer:    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:  1bill-to:  &id001    street: |             123 Tornado Alley            Suite 16    city:   East Centerville    state:  KSship-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"散列表。也可以在文件中加入选择性的空行,以增加可读性。在一个文件中,可同时包含多个文件,并用"---"分隔。选择性的符号"..."可以用来表示文件结尾(在利用流的通信中,这非常有用,可以在不关闭流的情况下,发送结束信号)。

YAMLYAML的高级组件

这部分算是一个后续的讨论,在比较各种数数据列语言时,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                     # 布林值"真"h: Yes we have No bananas  # 字串(包含"Yes"和"No")

YAML语法

在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介绍

YAML诞生

YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822。

Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。

YAML命名

YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。

在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种置标语言),

YAML功能

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表,标量等资料形态、。

它使用空白符号缩排和大量依赖外观的特色,特别适合用来表达或数据结构、各种设定档、倾印除错内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。

尽管它比较适合用来表达阶层式(hierarchical model)的数据结构,不过也有精致的语法可以表示关联性(relational model)的资料。

由于YAML使用空白字符和分行来分隔资料,使得它他特别适合用grep、Python、Perl、Ruby操作。

其让人最容易上手的特色是巧妙避开各种封闭符号,如:引号、各种括号等,这些符号在嵌套结构中会变得复杂而难以辨认。

YAML格式

YAML多行缩进

数据结构可以用类似大纲的缩排方式呈现,结构通过缩进来表示,连续的项目通过减号“-”来表示,map结构里面的key/value对用冒号“:”来分隔。样例如下:

house:  family:    name: Doe    parents:      - John      - Jane    children:      - Paul      - Mark      - Simone  address:    number: 34    street: Main Street    city: Nowheretown    zipcode: 12345

注意:

    字串不一定要用双引号标识;

    在缩排中空白字符的数目并不是非常重要,只要相同阶层的元素左侧对齐就可以了(不过不能使用TAB字符);

    允许在文件中加入选择性的空行,以增加可读性;

    在一个档案中,可同时包含多个文件,并用“——”分隔;

    选择性的符号“...”可以用来表示档案结尾(在利用串流的通讯中,这非常有用,可以在不关闭串流的情况下,发送结束讯号)。

YAML单行缩写

YAML也有用来描述好几行相同结构的数据的缩写语法,数组用''包括起来,hash用'{}'来包括。因此,上面的这个YAML能够缩写成这样:

house:  family: { name: Doe, parents: , children:  }  address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }

YAML适用场景

YAML脚本语言

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

YAML序列化

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

YAML配置文件

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

比如Ruby on Rails的配置就选用的YAML。对ROR而言,这很自然,也很省事.

由于兼容性问题,不同语言间的数据流转建议不要用YAML.

YAML语言比较

虽然YAML是参考JSON,XML和SDL等语言,不过跟这些语言比起来,YAML仍有自己的特色。

YAMLJSON

JSON的语法是YAML1.2版的子集,同时非常接近YAML1.0与1.1版的子集,因此大部分的JSON文件都可以被YAML的剖析器剖析。这是因为JSON的语法结构和YAML的内置格式相同。虽然大范围的分层也可以使用类似JSON的内置格式,不过YAML标准并不建议这样使用,除非这样编写能让文件可读性增加。YAML的许多扩展在JSON是找不到的,如:进阶资料形态、关系锚点、字串不需要双引号、映射资料形态会储存键值的顺序。

YAMLXML和SDL

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缩排划界

由于YAML的运作主要依赖大纲式的缩排来决定结构,这有效解决了界定符冲突(Delimiter collision)的问题。YAML的资料形态不依赖引号之特点,使的YAML文件可以利用区块,轻易的插入各种其他类型文件,如:XML、SDL、JSON,甚至插入另一篇YAML。

相反的,要将YAML置入XML或SDL中时,需要将所有空白字符和位势符号(potential sigils,如:<,>和&)转换成实体语法;要将YAML置入JSON中,需要用引号框住,并转换内部的所有引号。

YAML非阶层式的资料模型

跟SDL、JSON等,每个子结点只能有单一一个父节点的阶层式模型不同,YAML提供了一个简单的关系体制,可以从树状结构的其他地方,重复相同的资料,而不必显示那些冗余的结构。这点和XML中的IDRef类似,YAML剖析器在将YAML转换成物件时,会自动将那些参考资料的结构展开,所以程式在使用时并不会查觉到哪些资料是解码自这种结构。XML则不会将这种结构展开。这种表示法可以增加程式的可读性,并且,在那种“大部分参数维持和上次相同,只有少数改变”的设定档及通讯协定中,可以减少数据输入错误。一个例子是:“送货地点”和“购买地点”在发票的纪录中几乎都是相同的资料。

YAML实际的考量

YAML是“行导向的”,因此,就算想由现有程序的混乱输出,转换成YAML格式,并保留大部分的原始文件之外观,也非常简单。因为他不需要平衡封闭的标签、括号及引号,可以从很简单的利用程式,从报表产生YAML。同样,空格分隔可让使用行导向的命令如:grep、Awk、perl、ruby,和Python,来应急性的过滤YAML文件时更加方便。

特别是与标记语言不同的,连续的YAML区块导向往往是格式良好的YAML文件本身。这使得很容易撰写那种“在开始提取的具体记录之前,不需要‘读取全部文件内容’”的解析器(通常需要平衡起始和关闭标签、寻找引号和跳脱字符)。当处理一个单一静态的,整个存在内存中的数据结构将很大,或为提取一个项目来重建的整个结构,代价相当昂贵的记录档,这种特性是相当方便的。

值得讨论的是,尽管它的缩排方式似乎复杂化了深度很大的巢状层次,YAML将缩排视为一个单一的空白,这可能会取得比其他标记语言更好的压缩比。此外,极深的缩排可以完全避免的是:

使用“内置格式”(即简称类JSON格式)而无缩排;

使用关联锚点展开阶层以形成一个摊平的格式,使得YAML解析器能透明地重组成完整的数据结构。

YAML安全性

YAML是纯粹用来表达资料的语言,所以内部不会存代码注入的可执行命令。这代表剖析器会相当(至少)安全的解析文件,而不用担心潜在与执行命令相关的安全漏洞。举例来说,JSON是Javascript的子集,使用Javascript本身的剖析器是相当诱人的,不过也造成许多代码注入的漏洞。虽然在所有资料序列语言中,安全解析本质上是可能的,但可执行性却正是这样一个恶名昭彰的缺陷;而YAML缺乏相关的命令语言,可能相对安全。

YAML资料处理和呈现

XML和YAML规范提供非常不同的逻辑模型来进行资料结点的展现、处理及储存。

YAML函式库

YAML移植性

简单的YAML档案(例如:简单的键值对)不需要完整的YAML剖析器,便可以被RegEx解析。许多常用的编程语言──纯用某个语言,让函式库具有可携性──都有的YAML的产生器和剖析器。当效能比较重要时,也有许多和C语言绑定的函式库可使用。

YAMLC语言

libYAML

2007-06时,这个YAML的函式库渐趋稳定,并被YAML格式作者推荐使用。

SYCK

这个实现支持大部分1.0版的格式,并且被广泛的使用。它使用高阶interpreted languages进行最佳化。在2005之后,这个专案已经不再更新,不过仍可使用。

YAMLPerl

YAML::

一个通用的接口,被数个YAML剖析器使用。

YAML::Tiny

YAML简化版的实现。拥有小巧轻快的优点──比完整功能的YAML实现快上许多──并用纯Perl写成。

YAML::Syck

与SYCK函式库绑定。提供快速,highly featured的YAML剖析器。

YAML::XS

与LibYaml绑定。提供1.1版更好的相容性。

YAMLPHP

Spyc

纯PHP的实现。

PHP-Syck

与SYCK函式库绑定。

sfYaml

为symfony项目重写的Spyc, 可独立使用, 可以产生和剖析YAML文件。

YAMLPython

PyYaml

纯Python,或可选用LibYAML的函式库。

PySyck

与SYCK绑定。

YAMLRuby

从1.8版开始,YAML剖析器成为标准函式库之一。以SYCK为基础。

Ya2YAML

with full UTF-8 support

YAMLJava

jvyaml

以Syck为基础,and patterned off ruby-yaml

JYaml

纯Java的实现。

YAMLR

CRAN YAML

以SYCK为基础。

YAMLJavascript

原生的Javascript即可产生YAML,但不能剖析。

YAML Javascript

产生和剖析。

YAML.NET

待补充。

YAMLOCaml

OCaml-Syck

YAMLC++

用C++将libYaml包装。

YAMLObjective-C

Cocoa-Syck

YAMLLua

Lua-Syck

YAMLHaskell

Haskell Reference wrappers

YAMLXML

YAXML

currently draft only。

YAMLGo

Go-yaml

YAML常见错误与使用细节

建议使用能将跳格字符自动转换成空白字符的器,并且使用定宽度的字型。

器要能正确的处理UTF-8和UTF16编码(或是使用纯ASCII编码──它同时是UTF-8的子集)。

字串

YAML的字串不需使用引号,这可以避免使用复杂的转义字符,以增加可读性。然而,这有时也会导致错误,例如,字串本身是一个暧昧的字眼(像数字或布尔值);或在短句中意外的出现YAML的结构符号(常见的例子是由惊叹号起始的句子,或是包含冒号-空白的句子:"!Caca de vaca!"、"Caution: lions ahead")。这在发布YAML档案时并不造成困扰,但在制作小型指令码和人工档案时,这问题还蛮常出现的。比较好的方法是善用区块符号("|" or ">")而不要使用单行字串,来避免这种暧昧的表达方式。

预期实做的特性

YAML宿主语言

YAML相关概念

YAML没有自己的数据类型的定义,而是使用实现语言的数据类型。

例如,上面的那个YAML配置,在不同语言中解析后得到的数据类型并不相同。

PHP

$house = array('family' => array('name' => 'Doe','parents' => array('John', 'Jane'),'children' => array('Paul', 'Mark', 'Simone')),'address' => array('number' => 34,'street' => 'Main Street','city' => 'Nowheretown','zipcode' => '12345'));
PYTHON

house = {family: { name: Doe, parents: , children:  },address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }}

YAML讨论

这一点, 有可能是出奇制胜的地方,也可能是一个败笔。如果兼容性保证的不好的话,YAML数据在不同语言间流转会有问题。如果兼容性好的话,YAML就会成为不同语言间数据流通的桥梁。建议YAML官方设立兼容认证机制,每个语言的实现必须通过认证。

假如兼容性没问题的话,YAML就太完美了。轻巧,敏捷,高效,简便,通用。这才是理想中的数据模型。当然就现在而言,这还只是个理想。

热点导航
教育资讯 知道问答 公考资讯 司法考试 建筑知识 工作范文 大学排名 报考专业 学习方法 句子美文 秒知回答 作业解答 精选答案 知途问学