YAML 快速上手

文章目录

  • 1.语法
  • 2.历史版本
  • 3.数据结构
    • 对象
    • 数组
    • 复合结构
    • 标量
  • 4.引用
  • 5.文本块
  • 6.显示指定类型
  • 7.单文件多文档
  • 8.解析
  • 9.完整示例
  • 参考文献

YAML(YAML Ain’t a Markup Language)是专门用来写配置文件的语言,简洁强大,相比于 JSON 和 XML,更加便于开发人员读写。

YAML 配置文件后缀为.yml 或 .yaml。

1.语法

YAML 的基本语法规则如下:

  • 数据结构采用键值对的形式 key: value。
  • 键冒号后面要加空格(一般为 1 个空格)。
  • 字母大小写敏感。
  • 使用缩进表示层级关系。
  • 缩进只允许使用空格,不允许使用 Tab 键。
  • 缩进空格数可以任意,只要相同层级的元素左侧对齐即可。
  • 字符串值一般不使用引号,必要时可使用。使用双引号表示字符串时,会转义字符串中的特殊字符(例如\n)。使用单引号时不会转义字符串中的特殊字符。
  • 数组中的每个元素单独一行,并以 - 开头。或使用方括号,元素用逗号隔开。注意短横杆和逗号后面都要有空格。
  • 对象中的每个成员单独一行,使用键值对形式。或者使用大括号并用逗号分开。
  • 文档以三个连字符---表示开始,以三个点号...表示结束,二者都是可选的。
  • 文档前面可能会有指令,在这种情况下,需要使用---来表示指令的结束。指令是一个%后跟一个标识符和一些形参。
  • 目前只有两个指令:%YAML指定文档的 YAML 版本,%TAG用于 tag 简写。二者都很少使用。
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略。

2.历史版本

版本发布日期
YAML 1.029 January 2004
YAML 1.118 January 2005
YAML 1.2.021 July 2009
YAML 1.2.11 October 2009
YAML 1.2.21 October 2021

3.数据结构

YAML 支持的数据结构有三种:

  • 对象:键值对的集合,又称为映射(mapping)、散列(hashes)、字典(dictionary)。
  • 数组:一组按次序排列的值,又称为序列(sequence)、列表(list)。
  • 标量:单个不可再分的值

下面分别介绍这三种数据结构。

对象

对象的一组键值对,使用冒号结构表示。

name: Steve

YAML 也允许另一种写法,将所有键值对写成一个行内对象。

who: { name: Steve, age: 18 }

当然,如果对象元素太多一行放不下,那么可以换行。

who:name: Steveage: 18

数组

一组以连字符开头的行,构成一个数组。注意,连字符后需添加空格。

animals:- Cat- Dog- Goldfish

连字符前可以没有缩进,也就是说下面这种写法也是 OK 的,但是还是建议缩进,因为更加易读。

animals:
- Cat
- Dog
- Goldfish

数组也可以采用行内表示法。

animal: [Cat,Dog,Goldfish]

如果数组元素是一个数组,则可以在连字符下面再缩进输入一个数组。

animals:-- Cat- Dog-- Fish- Goldfish

如果是行内表示,则为:

animals: [[Cat,Dog],[Fish,Goldfish]]

如果数组元素是一个对象,可以写作:

animals:- species: dogname: foo- species: catname: bar

对应的 JSON 为:

{"animals": [{"species": "dog","name": "foo"},{"species": "cat","name": "bar"}]
}

复合结构

对象和数组可以结合使用,形成复合结构。

languages:- Ruby- Perl- Python 
websites:YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org 

对应的 JSON 表示如下:

{"languages": ["Ruby","Perl","Python"],"websites": {"YAML": "yaml.org","Ruby": "ruby-lang.org","Python": "python.org","Perl": "use.perl.org"}
}

标量

标量是最基本、不可再分的值。有以下 7 种:

  • 字符串
  • 布尔值
  • 整数
  • 浮点数
  • Null
  • 时间
  • 日期

使用一个例子来快速了解标量的基本使用:

boolean: - TRUE	# true、True 都可以- FALSE	# false、False 都可以
float:- 3.14			# 数值直接以字面量的形式表示- 6.8523015e+5	# 可以使用科学计数法
int:- 123							# 数值直接以字面量的形式表示- 0b1010_0111_0100_1010_1110	# 二进制表示
null:nodeName: 'node'parent: ~  		 # 使用~表示 null
string:- hello			 # 字符串默认不使用引号- "Hello world"  # 使用双引号或单引号包裹含有空格或特殊字符(如冒号)的字符串- newlinenewline1		 # 字符串可以拆成多行,每一换行符会被转化成一个空格
date:- 2018-02-17     # 日期必须使用 ISO 8601 格式,即 yyyy-MM-dd
datetime:- 2018-02-17T15:02:31+08:00    # 时间使用 ISO 8601 格式,时间和日期之间使用 T 连接,+08:00 表示时区

YAML 字符串有三种表示方式:

  • 无引号
  • 双引号
  • 单引号

字符串默认不需要引号,但是如果字符串包含空格或特殊字符(如冒号),需要加引号。

双引号字符串允许在字符串中使用转义序列来表示特殊字符,例如 \n 表示换行,\t 表示制表符,以及 \" 表示双引号。

单引号字符串被视为纯粹的字面字符串,不支持转义序列。

如果字符串含有单引号,可以使用双引号包裹,反之亦然。

4.引用

锚点 & 和别名 *,可以用来完成引用。

defaults: &defaultsadapter:  postgreshost:     localhostdevelopment:database: myapp_development<<: *defaults

等同于下面的配置。

defaults:adapter:  postgreshost:     localhostdevelopment:database: myapp_developmentadapter:  postgreshost:     localhost

& 用来建立锚点(defaults),<< 表示合并到当前数据,* 用来引用锚点。

5.文本块

如果想引入多行的文本块,可以使用 ||+|->>+>-

  • |

当内容换行时,保留换行符。

如果最后一行有多个换行符,只保留一个换行符。

linefeed1: |sometext
linefeed2: |sometextlinefeed3: |sometext

对应的 JSON 为:

{"linefeed1": "some\ntext\n","linefeed2": "some\ntext\n","linefeed3": "some\n\ntext\n"
}
  • |+

当内容换行时,保留换行符。

与 | 的区别是,如果最后一行有多个换行符,则保留实际数目。

linefeed1: |+sometext
linefeed2: |+sometextlinefeed3: |+sometext

对应的 JSON 为:

{"linefeed1": "some\ntext\n","linefeed2": "some\ntext\n\n","linefeed3": "some\n\ntext\n"
}
  • |-

当内容换行时,保留换行符,但最后的换行符不保留。

linefeed1: |-sometext
linefeed2: |-sometextlinefeed3: |-sometext

对应的 JSON 为:

{"linefeed1": "some\ntext","linefeed2": "some\ntext","linefeed3": "some\n\ntext"
}
  • >

当内容换行时,替换为空格,但保留最后一行的换行符。

如果最后一行有多个换行符,只保留一个换行符。

linefeed1: >sometext
linefeed2: >sometextlinefeed3: >sometext

对应的 JSON 为:

{"linefeed1": "some text\n","linefeed2": "some text\n","linefeed3": "some\ntext\n"
}
  • >+

当内容换行时,替换为空格,但保留最后一行的换行符。

与 > 的区别是,如果最后一行有多个换行符,则保留实际数目。

linefeed1: >+sometext
linefeed2: >+sometextlinefeed3: >+sometext

对应的 JSON 为:

{"linefeed1": "some text\n","linefeed2": "some text\n\n","linefeed3": "some\ntext\n"
}
  • >-(缺省行为)

当内容换行时,替换为空格,不保留最后一行的换行符。

linefeed1: >-sometext
linefeed2: >-sometextlinefeed3: >-sometext

对应的 JSON 为:

{"linefeed1": "some text","linefeed2": "some text","linefeed3": "some\ntext"
}

注意:以上 6 个特殊字符,|->- 用得最多。

6.显示指定类型

有时需要显示指定某些值的类型,可以使用 !(感叹号)显式指定类型。

! 单叹号通常是自定义类型,!! 双叹号是内置类型。

# !!str 指定为字符串
string.value: !!str HelloWorld!
# !!timestamp 指定为日期时间类型
datetime.value: !!timestamp 2021-04-13T02:31:00+08:00

内置的类型如下:

!!int:整数类型
!!float:浮点类型
!!bool:布尔类型
!!str:字符串类型
!!binary:二进制类型
!!timestamp:日期时间类型
!!null:空值
!!set:集合类型
!!omap,!!pairs:键值列表或对象列表
!!seq:序列
!!map:散列表类型

7.单文件多文档

一个 yaml 文件可以包含多个 yaml 文档,使用三个连字符---分隔。

a: 10
b: - 1- 2- 3
---
a: 20
b: - 4- 5 

这种情况在 K8S 和 SpringBoot 中非常常见。

比如 SpringBoot 在一个 application.yml 文件中,通过 — 分隔多个不同配置,根据 spring.profiles.active 的值来决定启用哪个配置。

# 公共配置
spring:profiles:active: prod #使用名为 prod 的配置,这里可以切换成 dev。datasource:url: jdbc:mysql://localhost:3306/test_db?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=truepassword: 123456username: root
---
# 开发环境配置
spring:profiles: dev #profiles属性代表配置的名称。server:port: 8080
---
# 生产环境配置
spring:profiles: prodserver:port: 80

8.解析

下面以 YAML 表示一个简单的后台服务配置:

name: UserProfileServer
maxconns: 1000
queuecap: 10000
queuetimeout: 300
loginfo:loglevel: ERRORlogsize: 10Mlognum: 10logpath: /usr/local/app/log

下面以 Go 语言为例,解析上面的 YAML 配置。

因为 Go 官方并没有提供解析 YAML 的标准库,所以这里基于第三方开源库 go-yaml 来完成对 YAML 文件的解析。

第一步,将 YAML 配置文件的内容在 Convert YAML to Go struct 转换为 Go struct。

type Server struct {Name         string `yaml:"name"`Maxconns     int    `yaml:"maxconns"`Queuecap     int    `yaml:"queuecap"`Queuetimeout int    `yaml:"queuetimeout"`Loginfo      struct {Loglevel string `yaml:"loglevel"`Logsize  string `yaml:"logsize"`Lognum   int    `yaml:"lognum"`Logpath  string `yaml:"logpath"`} `yaml:"loginfo"`
}

第二步,利用第三方开源库 go-yaml 来完成对 YAML 文件的解析。

package mainimport("io/ioutil""fmt""os"	yaml "gopkg.in/yaml.v3"
)func main() {file, err := os.Open("server.yaml")if err != nil {fmt.Printf("error:%v\n", err)return}defer file.Close()data, err := ioutil.ReadAll(file)if err != nil {fmt.Printf("error:%v\n", err)return}v := Server{}err = yaml.Unmarshal(data, &v)if err != nil {fmt.Printf("error:%v\n", err)return}fmt.Printf("%+v\n", v)
}

运行输出:

{Name:UserProfileServer Maxconns:1000 Queuecap:10000 Queuetimeout:300 Loginfo:{Loglevel:ERROR Logsize:10M Lognum:10 Logpath:/usr/local/app/log}}

9.完整示例

%YAML 1.2
---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:given:   Dorothyfamily:  Galeitems:- part_no:   A4786descrip:   Water Bucket (Filled)price:     1.47quantity:  4- part_no:   E1628descrip:   High Heeled "Ruby" Slipperssize:      8price:     133.7quantity:  1bill-to:  &id001street: | 123 Tornado AlleySuite 16city:   East Centervillestate:  KSship-to:  *id001   specialDelivery:  >Follow the Yellow BrickRoad to the Emerald City.Pay no attention to theman behind the curtain.
...

注意在 YAML 中,字符串不一定要用双引号标示。另外,在缩进中空白字符的数目并不是非常重要,只要相同层次结构的元素左侧对齐就可以了(不过不能使用 TAB 字符)。

%YAML 1.2 表示版本。

这个文件的顶层由七个键值组成:其中一个键值"items",是两个元素构成的数组(或称清单),这数组中的两个元素同时也是包含了四个键值的散列表。

文件中重复的部分用这个方法处理:使用锚点(&)和引用(*)标签将"bill-to"散列表的内容复制到"ship-to"散列表。也可以在文件中加入选择性的空行,以增加可读性。

在一个文件中,可同时包含多个文件,并用---分隔。选择性的符号...可以用来表示文件结尾(在流通信中,这非常有用,可以在不关闭流的情况下,发送结束信号)。


参考文献

The Official YAML Web Site
Convert YAML to JSON
go-yaml - Github
Convert YAML to Go struct
YAML 详解与实战-CSDN
YAML - 维基百科,自由的百科全书
Brief YAML reference — Camel 0.1.2 documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/30245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R包开发详细教程

开发一个R包可以帮助你组织和共享代码。以下是一个详细的步骤教程&#xff0c;介绍如何开发一个R包。 步骤 1: 准备工作 确保你已经安装了以下R包&#xff1a; install.packages("devtools") install.packages("roxygen2") install.packages("test…

[机器学习算法]决策树

1. 理解决策树的基本概念 决策树是一种监督学习算法&#xff0c;可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征&#xff0c;节点之间的分支表示特征的可能取值&#xff0c;叶节点表示分类或回归结果。 2. 决策树的构建…

基于深度学习的图像压缩

基于深度学习的图像压缩 图像压缩是指将图像数据量减小的同时尽量保留其视觉质量的过程。传统的图像压缩方法&#xff08;如JPEG、PNG等&#xff09;已经广泛应用&#xff0c;但随着深度学习技术的发展&#xff0c;基于深度学习的图像压缩方法逐渐显现出其优越性。以下是一些关…

【AI原理解析】— Kimi模型

目录 一、技术背景与基础 二、核心技术特点 深度学习与神经网络&#xff1a; 超长上下文学习&#xff1a; 多模态对齐&#xff1a; 个性化调优&#xff1a; 知识增强&#xff1a; 推理优化&#xff1a; 三、模型架构 一、技术背景与基础 Kimi模型是一种基于深度学习和…

enum库

Python enum 模块教程 enum 是 Python 3.4 引入的一个模块&#xff0c;用于定义枚举类型。枚举类型是一种特殊的数据类型&#xff0c;由一组命名的值组成&#xff0c;这些值称为枚举成员。使用 enum 可以提高代码的可读性和可维护性&#xff0c;特别是在处理一组相关的常量值时…

Laravel 的事件监听器与服务提供者和服务容器的二三事

一. Laravel 的事件监听器与服务提供者和服务容器有密切的关系。 服务提供者用于注册服务、绑定依赖关系以及执行框架的初始化设置。在服务提供者的 register 方法中&#xff0c;可以注册事件和事件监听器。 服务容器则负责管理对象的创建和依赖注入。事件监听器通常会被注册…

人工智能和机器学习的应用日益广泛,在医疗健康领域的具体应用是什么?

人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;在医疗健康领域的应用日益广泛&#xff0c;涵盖了从疾病预测、辅助诊断、药物研发到健康管理等多个方面。以下是一些具体的应用实例和成功案例&#xff1a; 疾病预测与辅助诊断&#xff1a;机器学习算…

实现Spring Boot中多数据源配置的解决方案

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN博客专家&#xff0c;华为云云享专家&#xff0c;阿里云专家博主 &#x1f4cc; 擅长领域&#xff1a;全栈工程师、爬虫、ACM算法 &#x1f525; 微信&#xff1a;zsqtcyw 联系我领取学习资料 …

python实现进度条的方法和实现代码

在Python中&#xff0c;有多种方式可以实现进度条。这里&#xff0c;我将介绍七种常见的方法&#xff1a;使用tqdm&#xff08;这是一个外部库&#xff0c;非常流行且易于使用&#xff09;、rich、click、progressbar2等库以及纯Python的print函数与time库来模拟进度条。 目录…

《STM32 HAL库》小米微电机控制例程——通信协议分析及驱动库

之前有段时间因为机器狗项目的缘故&#xff0c;一直在使用小米微电机&#xff0c;但是苦于没有一个详尽的奶妈级教程&#xff0c;在控制电机的学习中踩了不少的坑。今天咱们就从头至尾一步一步的实现使用按键控制小米微电机。本文将会分析小米电机驱动库&#xff0c;并简要介绍…

Spring Boot 项目中的如何序列化日期格式字符串(对象转JSON的日期字符串格式)

在Spring Boot 项目中, 将Bean序列化为一个JSON字符串的时候, 对于日期类型的属性, 可以直接在属性上使用@JsonFormat即可达成, 但是如果属性本身就是一个日期的字符串, 要输出为另外格式字符串要如何实现呢? @JsonFormat 转换 Timestamp 类型的属性 @JsonFormat注…

linux系统中,pwd获取当前路径,dirname获取上一层路径;不使用 ../获取上一层路径

在实际项目中&#xff0c;我们通常可以使用 pwd 来获取当前路径&#xff0c;但是如果需要获取上一层路径&#xff0c;有不想使用 …/ 的方式&#xff0c;可以尝试使用 dirname指令 测试shell脚本 #!/bin/bash# 获取当前路径 CURRENT_PATH$PWD echo "CURRENT_PATH$CURREN…

练手代码之使用Python实现合并PDF文件

如果你有合并PDF的需要&#xff0c;你会怎么办 我们无所不能的程序员会选择写一个Python代码来实现&#xff08;谁会这么无聊&#xff1f;是我&#xff09;&#xff0c;如果真的有PDF操作需要&#xff0c;我推荐你使用PDF Expert这个软件哈~ 话不多说直接上代码&#xff1a; …

【Ruby简单脚本01】查看wifi密码

脚本 # 使用io库 def get_cmd_result(cmd) IO.popen(cmd,:external_encoding>GBK).read.encode("utf-8") end def list_wifi wifi_pwds Hash.new # 获取所有wifi文件 o1 get_cmd_result("netsh wlan show profiles") # 获取所有匹配结果 …

Linux操作系统学习:day05

内容来自&#xff1a;Linux介绍 视频推荐&#xff1a;[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( 目录 day0530、删除用户31、添加和删除用户组创建用户组删除用户组 32、修改密码33、使用tar工具进行压缩和解压缩压缩解压缩 34、使用zip u…

增强大型语言模型(LLM)可访问性:深入探究在单块AMD GPU上通过QLoRA微调Llama 2的过程

Enhancing LLM Accessibility: A Deep Dive into QLoRA Through Fine-tuning Llama 2 on a single AMD GPU — ROCm Blogs 基于之前的博客《使用LoRA微调Llama 2》的内容&#xff0c;我们深入研究了一种称为量化低秩调整&#xff08;QLoRA&#xff09;的参数高效微调&#xff0…

单片机第五季-第八课:STM32CubeMx和FreeRTOS

1&#xff0c;FreeRTOS背景介绍 RTOS简介&#xff1a; 实时操作系统&#xff0c;本用于追求实时性的嵌入式系统&#xff0c;典型&#xff1a;ucos/uclinux/vxworks&#xff1b; 特点&#xff1a;中断响应快、一般可嵌套中断、使用实地址、多任务&#xff1b; &#xff08;实…

Qt6视频播放器项目框架代码

视频播放的关键代码如下: 使用Qt6的QMediaPlayer,QVideoWidget实现 void FunnyWidget::initVideo() {player = new QMediaPlayer(this);videoWidget = new QVideoWidget(this);playButton = new QPushButton("Play", this);pauseButton = new QPushButton("…

项目的打包

一:打包到微信小程序 1)vscode打包 2)在微信小程序开发工具中打开路径,上传. 疑问:为什么pnpm bulid:mp-weixin用于打包,pnpm dev:mp-weixin也可生成对应路径下的文件?? 打包的是没有热重载,且打包体积更小. 二:条件编译 vscode可以打包成能在不同平台上运行的代码.但是有…

404、左叶子之和

题解&#xff1a;可以采用后序递归遍历的方式&#xff0c;先将左右子树的左叶子节点值计算出来&#xff0c;最后相加。 当遍历到左叶子节点的父节点时就开始处理&#xff0c;将左叶子节点的值记录下来。 代码如下&#xff1a; class Solution { public:int sumOfLeftLeaves(…