侧边栏壁纸
  • 累计撰写 43 篇文章
  • 累计创建 19 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

YAML教程

李丰华
2022-12-02 / 0 评论 / 0 点赞 / 53 阅读 / 0 字

YAML 的名字🤓

根据YAML 1.0 规范文档 (2001-05-26) YAML 是 Yet Another Markup Language 首字母缩略词,但后来为了和真正的标记语言区分,在2002-04-07 标准中改为 YAML Ain't Markup Language 的首字母缩写,缩写字母里面还有 YAML 这其实是个递归缩写。

YAML(/ˈjæməl/) 的发音 [jeml],YAML 前取 Yet 的 [je] 发音,后押英文单词 camel(骆驼) 的 [ml] 。

YAML 的特点

  • YAML是一种非常简单的基于文本的人类可读的语言,用于在人和计算机之间交换数据。
  • YAML不是一种编程语言。它主要用于存储配置信息
  • YAML 的缩进就像 Python 的缩进一样优雅。
  • YAML 还减少了 JSON 和 XML 文件中的大部分“噪音”格式,例如引号、方括号和大括号。

YAML 需要注意的

  • YAML区分大小写
  • YAML 不允许使用制表符 Tab 键,(你之所按下 Tab YAML 仍能使用,是因为编辑器被配置为按下 Tab 键会导致插入适当数量的空格)。
  • YAML是遵循严格缩进的。

YAML 基本使用

因为我们最熟悉的是 JSON,YAML 又是 JSON 的超集,可以通过简单的转换,让我们更容易的理解 YAML 的语法,这里有个不错的在线工具 codebeautify,你可以随时把写好的 YAML 语法转化为 JSON,来帮助你理解,不过并不建议你强烈依赖它。

后缀名

YAML 文件的后缀名是 .yaml.yml,本着能少写不多写的原则,我们常用的是.yml

键值对

YAML 易学就在这里,即使你没学习过任何 YAML 的语法,你也能大致看懂 YAML 文件,而 YAML 文件,最常见的就是键值对,常见的称法是对象、map 或 dict。

<key>: <value> 

其中<key>代表 名称<value>代表 数据 ,之间用分隔:(空格是必需的)。

name: CondorHero
age: 18

对应到 JSON:

{
    "name": "CondorHero",
    "age": 18
}

列表

说数组大家可能更加熟悉,列表通过在其项目前加上-(连字符)来表示。

number: 
    - One
    - Two
    - Three

对应到 JSON:

{
    "number": [
        "One",
        "Two",
        "Three"
    ]
}

这个列表是包含在对象里面的,如果我们像直接要一个数组呢,比如说下面这个 JSON 列表:

[
    {
        "name": "CondorHero",
        "age": 18
    },
    {
        "name": "Shavahn",
        "age": "16"
    }
]

对应的 YAML 我们就可以这么写:

- 
    name: CondorHero
    age: 18
- 
    name: Shavahn
    age: 16

注释

这个就很强大了,YAML 作为配置文件比 JSON 更流行,一在易读,而就在支持注释。YAML 的注释和 Bash、Python 的注释一样。例如:

# 这是一行注释

YAML不支持或者多行注释。

多文档

在一个文件里面创建多个文档,它以三个破折号(---)开头,以三个句点(...)结束,开始和结束都是可选的,开头可以单独使用,但结束不能单独使用。

这个用的不多但很强大,可以把相同或类似的部分归为同一部分。

---
 - XML
 - JSON
 - CSV
---
 - Unicode
 - ASCII
 - UTF8
...

对应在 JSON 中:

[
    "XML",
    "JSON",
    "CSV",
    "Unicode",
    "ASCII",
    "UTF8"
]

以下介绍的 YAML 语法在其他语言可能并没有实现。


Pairs

Pairs 是允许重复的命名值的有序列表。许多编程语言没有这种数据类型,因此应用程序可能会解释成对作为哈希表数组,每个哈希表包含一个键。请参见下面的示例以了解其用法。

这个有点像 JS 中 key 为 symbol 的对象。

# Explicitly typed pairs.
Block tasks: !!pairs
  - meeting: standup
  - meeting: demo
  - break: lunch
  - meeting: all hands
Flow tasks: !!pairs [ meeting: standup, meeting: lunch ]

Set

Set 更多的叫法是集合,它是具有不同值的无序节点集合,数组去重最快捷的方法了。请参见下面的示例以了解其用法。

# Explicitly typed set.
players: !!set
  ? Mark
  ? Steve
  ? Smith

# Flow style
soccer teams: !!set { Chelsea, Arsenal, Liverpool }

Python 是支持这种数据类型的,上面的代码在 Python 展示为:

你可以通过这个网站 http://yaml-online-parser.appspot.com/ 来把 YAML 编译成 Python 代码。

YAML 中的类型

Perl, Python, PHP, Java, C#, Ruby, and JavaScript 等大多数语言有的类型,YAML 都能很好地支持。

YAML 支持的数据类型列表如下:

  • Boolean
  • Numbers
  • Strings
  • Arrays
  • Maps
  • Null
  • Dates
  • Timestamp

关于变量这里有个好玩的事情,变量对应的英文单词是 variable,YAML 还可以用另一个单词 scalars 标量。不过也能理解 YAML 里面没有变量的定义,都是直接使用,所以数据类型更多像用于区分类型,这难道不是衡量标准吗,所以叫标量很合适。(这个异曲同工之妙就像 Typescript 中的类型注解一样)

比如:

dataType:
  string: "YAML"
  integer: 123
  float: 12.345
  boolean: No

编译成 JSON:

{
    "dataType": {
        "string": "YAML",
        "integer": 123,
        "float": 12.345,
        "boolean": "No"
    }
}

字符串(string)

字符串可以加单引号或双引号或者没有引号。

quoted: 
    - 'single quoted string'
    - "double quoted strings"
    - withoout quoted string

上面定义的字符串都是有效的,编译成 JSON 如下:

{
    "quoted": [
        "single quoted string",
        "double quoted strings",
        "withoout quoted string"
    ]
}

单行/多行文本

涉及到字符串还有一个问题,当字符串比较多的时候,更好的展示,选择单行/多行文本展示。

例如,配置 GitHub Actions 时候运行一些命令:

# Multiline strings start with |
execute: |
    npm ci
    npm build
    npm test

编译成 JSON:

{
    "execute": "npm ci\nnpm build\nnpm test\n"
}

例如,你想通过换行让 YAML 更加易读,而真正展示的时候是单行:

single-line-string: > 
    This
    should
    be
    one
    line

这就是它在 JSON 中的样子:

{
    "single-line-string": "This should be one line\n"
}

Notion: 当使用 > 字符而不是 时 | ,每一个新行都将被解释为一个空格

数值(Number)

数值有整数、小数、正数、负数、正无穷大、负无穷大、NaN(not a number)、科学计数法、进制表示。

例如:

integer: 12
decimal: 0.5
positive: +12
negative: -12
positive infinity: .inf
negative infinity: -.inf
not a number: .nan
# JS 数值可以通过下划线分割
number: 687_456
scientific counting method: 2.3e4
# 二进制
binary: 0b101010

通过 js-yaml 转换为 JS 对象如下:

{ 
    integer: 12,
    decimal: 0.5,
    positive: 12,
    negative: -12,
    'positive infinity': Infinity,
    'negative infinity': -Infinity,
    'not a number': NaN,
    number: 687456,
    'scientific counting method': 23000,
    binary: 42 
 }

布尔(boolean)

boolean: true

编译为 JSON:

{
    "boolean": true
}

用于表示真假,你在其他地方可能看到还可以使用 True/False, ON/OFF, Yes/Noy/n

根据YAML 1.2 规范文档, “yes”和“no” 等不再被解释为布尔值。

We have removed unique implicit typing rules and have updated these rules to align them with JSON's productions. In this version of YAML, boolean values may be serialized as “true” or “false”;

我们删除了独特的隐式类型规则并更新了这些规则以将它们与 JSON 的产生式保持一致。在这个版本的 YAML 中,布尔值可能被序列化为“true”或“false”;

不过,您可以使用 !!bool 来解析它们,这个就属于显示声明类型 tags 标签的内容了。

当然了,我更推荐直接 true 和 false 了。

空值(null)

YAML 声明空值有以下几种方法:

manager: null
blank:
tilde: ~
title: null
~: null key

编译成 JOSN:

{
    "manager": null,
    "blank": null,
    "tilde": null,
    "title": null,
    "null": "null key"
}

时间戳(timestamp)

时间戳表示单个时间点。它使用符号形式 ISO8601。如果未添加时区,则假定该时区为 UTC。要描述日期格式,可以省略时间部分。在这种情况下,时间默认为00:00:00Z。请参见下面示例中的用法。

time: 2020-12-07T01:02:59:34.02Z
timestamp: 2020-12-07T01:02:59:34.02 +05:30
datetime: 2020-12-07T01:02:59:34.02+05:30
notimezone: 2020-12-07T01:02:59:34.02
date: 2020-12-07

类型值对照表

最后总结一张对照表:

描述
~, null, Nullnull values
1234decimal
0b101010binary (base 64 encoding)
0x12ADhexadecimal
02677octal
.inf, -.Infinfinity
.NANnot a number
truetrue
falsefalse
2020-12-07date or timestamps
123_456.78floating point or decimal numbers
123.45e+78exponential numbers

显示类型

默认情况下,YAML 会自动推断数据类型,就像 TypeScript 的类型推断一样,但是当你需要你也可以使用 标签(tags)显示指定类型,比如整数类型 两个英文感叹号 !! 再加上 int 就变成了一个整数 tag ——!!int

# The following value should be an int, no matter what:
should-be-int: !!int 3.2

# Parse any value to string:
should-be-string: !!str 30.25

# I need the next value to be boolean:
should-be-boolean: !!bool yes

编译成 JSON:

{
    "should-be-int": 3,
    "should-be-string": "30.25",
    "should-be-boolean": true
}

我这里也整理了一张表:

tagsdescription
!!intinteger
!!floatfloat
!!strstring
!!boolboolean
!!nullnull
!!seqArray
!!mapmap
!!setset
!!omaporder map
!!pairspairs

高级功能

代码复用 Node Anchors

任何代码都讲究个复用,最基本的就是定义变量,但 YAML 无法定义变量,那么怎么做代码复用来,YAML 有自己的解决方案,通过 Node Anchors

例如,复用 Value 值:

First occurrence: &anchor Value
Second occurrence: *anchor

对应的 JSON 文件:

{
    "First occurrence": "Value",
    "Second occurrence": "Value"
}

通过 & 标记一个节点,使用 * 字符引用它,从而达到复用。

块样式和流样式

块样式

在文档块样式使用块用于结构化文档。它更容易阅读,但不那么紧凑,例子

color: 
  - red
  - yellow
  - blue

流样式

YAML有一种称为flow style的替代语法,它允许在不依赖缩进的情况下内联编写序列映射,分别使用一对方括号[]和大括号{}

Flow 风格是JSON. 它不太容易阅读;然而,它提供了更多的紧凑性。

color: [red, blue]

 - { name: "CondorHero", age: 18 } 

YAML 与 JSON 的关系

你可能听说过 YAML 和 JSON 之间的超集与子集这样的关系,这个可以推荐你阅读 YAML1.2 版本的官方文档 1.3 小节 Relation to JSON

这里偷来 Google 翻译的:

实践中也是如此;每个 JSON 文件也是一个有效的 YAML 文件。

XML、JSON、YAML

看下图,从左往右是 XML、JSON、YAML 文件,JSON 通过 {}[] 等简化了 XML,变得更加直观,但是当嵌套过深 XML 需要找结尾标签,JSON 需要找结尾的 },无论 XML 还是 JSON 都需要找结尾标记,很不直观,但 YAML 直接做的比 JSON 更加激进,连符号都没了,立体结构也变得扁平了,更加符合人类阅读习惯。

当我们从 XML 过渡到 JSON 的时候,你会惊叹,哇哦,少了这么多字符,优雅的符号变现更加直观,这真是绝绝子,现在当你看到 YAML,仔细了解了它的语法,肯定惊呼,哇哦,这么简洁的吗,那种感受不亚于从 XML 过渡到 JSON。

如果你熟悉 Markdown 和 HTML,YAML 的优雅写法丝毫不亚于从 HTML 迁移到 Markdown 。

但是请注意的一点是,YAML 革命 JOSN 只限定在书写配置文件这个领域,不同设备的数据交互,依然是 JSON,因为它获得更好的兼容性更能被大多属于语言识别。

YAML 频繁出现在哪些应用上

你或多或少肯定用过 YAML 作为配置文件,但你可能想不到它已经大规模的应用到各种应用上。

比如:

  • GitHub Action
  • Swagger
  • VuePress 等各种博客的配置文件
  • Docker
  • Kubernetes(K8s)
  • Ansible
  • Azure DevOps
  • Jenkins
  • ...

对于前端,甚至可以大胆想象,从简单易读的方面来讲,前端 Babel、Eslint、TypeScript 等配置文件完全可以直接 YAML 取代。

需要注意的是,各个语言无法直接识别 YAML 文件,需要借助对应语言对应 YAML 库,例如 Python 是 PyYAML、Go 是 go-yam、JavaScript 是 js-yaml 等等。

工具汇总

因为各种语言没有对 YAML 提供了原生支持,所以还是在线调试比较方便,下面是我用到的几个使用 YAML 网站,主要包括了校验、美化、转换

  1. 校验 YAML 语法的正确性
  2. 美化
  3. 转换

总结

今天我们先了解了 YAML 名字,总结了 YAML 的特点和值得注意的地方,然后就是 YAML 的基本用法,后学习了高级用法,通过对比 XML、JSON、YAML 明白了数据序列化的演变,明白了 YAML 为何能取得开发者的芳心,作为配置文件出现在各大应用上面。

参考

0

评论区