YAML 是什么?小白也能看懂的定义、用法与案例
一、YAML 到底是什么?一句话讲清楚
YAML,全称 "YAML Ain't a Markup Language"(YAML不是一种标记语言),这是一个递归缩写。在开发这门语言时,它的意思其实是 "Yet Another Markup Language"(仍是一种标记语言)。但为了强调它以数据为中心,而非以标记为重心,所以用了这个反向缩写。
你可以把它理解为:一种专门写给人看的数据文件格式。
它的语法和其他高级语言类似,可以简洁地表达清单(数组)、散列表(字典)、标量(单个值)等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件。
YAML 文件的后缀名为 .yml 或 .yaml,两者完全等价,没有任何区别。
二、为什么 YAML 这么火?四大核心优势
| 特性 | YAML | JSON | TOML |
|---|---|---|---|
| 支持注释 |
✅ 支持 # 注释 | ❌ 不支持 | ✅ 支持 |
| 语法简洁度 | 缩进式,无多余符号 |
大量 {} [] "" | 键值对,中等符号量 |
| 数据类型丰富度 | 字符串/数字/布尔/日期/数组/对象/锚点 | 仅6种基础类型 | 丰富但无锚点 |
| 人类可读性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 缩进表达层级 | ✅ 天然支持 | ❌ 无层级概念 | ❌ 无层级概念 |
YAML 的四大核心优势:
极度易读:没有花括号、没有引号堆砌,看一眼就知道数据结构是什么
支持注释:这是它碾压 JSON 的杀手锏,配置文件没有注释等于灾难
功能强大:锚点引用、多文档、多行字符串、类型标签,JSON 和 TOML 都不具备
生态成熟:Docker、Kubernetes、Spring Boot、GitHub Actions、Ansible 全部原生支持
三、YAML 核心语法:五条铁律,背下来就够了
YAML 的语法极其简单,但有几条铁律,违反任何一条都会报错。
铁律一:大小写敏感
Name 和 name 是两个完全不同的键。所有键和值都区分大小写。
铁律二:缩进表示层级,且只能用空格
这是 YAML 最重要的规则:缩进不允许使用 Tab,只允许使用空格。 缩进的空格数不重要,只要相同层级的元素左对齐即可,一般建议统一使用 2 个空格。
# ✅ 正确:使用空格缩进 person: name: Alice age: 30 # ❌ 错误:使用 Tab 缩进(会解析失败) person: name: Alice
铁律三:冒号后面必须加一个空格
key:value 是错误的,**必须写成 key: value**(冒号后有一个空格)。
# ✅ 正确 name: Alice # ❌ 错误 name:Alice
铁律四:# 表示注释
从 # 开始直到行尾的所有内容都是注释,解析器会完全忽略。
# 这是一行完整的注释 name: Alice # 这是行尾注释,也可以用
铁律五:短横线 - 加空格表示列表项
fruits: - apple - banana - orange

四、YAML 支持的数据类型(重点)
YAML 能自动识别类型,这是它比 JSON 强大得多的地方。
| 数据类型 | 示例 | 说明 |
|---|---|---|
| 字符串 | name: Alice |
默认即为字符串,也可用 '单引号' 或 "双引号" |
| 整数 | age: 30 |
支持十进制、二进制 0b1010、十六进制 0xFF |
| 浮点数 | price: 3.14 |
支持科学计数法 6.85e+5 |
| 布尔值 | enabled: true |
只支持 true/false、yes/no、on/off |
| 空值 | parent: ~ |
使用 ~ 或 null 表示 |
| 日期 | date: 2026-06-16 |
必须使用 ISO 8601 格式 yyyy-MM-dd |
| 日期时间 | datetime: 2026-06-16T10:24:00+08:00 | ISO 8601 格式,T 连接日期和时间 |
| 数组 | colors: [red, green, blue] | 支持行内写法和多行写法 |
| 对象(映射) | person: {name: Alice, age: 30} | 键值对集合,类似 JSON 对象 |
关于字符串的四种写法(非常重要):
| 写法 | 语法 | 行为 | 适用场景 |
|---|---|---|---|
| 普通字符串 | 不加引号 | 自动去除首尾空格 | 大多数情况 |
| 单引号字符串 | '...' | 原样输出,不转义任何字符 | 路径、正则表达式 |
| 双引号字符串 | "..." |
支持转义字符(\n 换行等) | 需要转义的文本 |
| 字面量块 | | 或 > | 多行文本(下面详解) | 大段文字 |
关键区别:单引号字符串不处理任何转义字符,所见即所得。 这对写 Windows 路径极其友好:
# 推荐:单引号,反斜杠不会被转义 path: 'C:\Users\Tom\Documents\file.txt' # 不推荐:双引号,需要双写反斜杠 path: "C:\\Users\\Tom\\Documents\\file.txt"
五、YAML 的三大高级特性(杀手级功能)
1. 多行字符串:| 和 >
| 符号 | 名称 | 行为 | 示例 |
|---|---|---|---|
| | 保留换行(块字面量) | 保留所有换行符 | desc: | Line1\nLine2 → 两行 |
> | 折叠换行(块折叠) | 换行符替换为空格 | desc: > Line1\nLine2 → 一行 |
# | 保留换行 description: | 这是第一行 这是第二行 这是第三行 # 结果:三行文本,保留所有换行 # > 折叠为一行 summary: > 这是第一行 这是第二行 # 结果:"这是第一行 这是第二行"(换行变空格)
2. 锚点与引用:& 和 *(YAML 独有,JSON/TOML 都没有)
这是 YAML 最强大的特性之一:用 & 定义锚点,用 * 引用锚点,用 << 合并内容。
# 定义锚点 defaults: &defaults adapter: postgres host: localhost port: 5432 # 引用锚点(合并) development: database: myapp_dev <<: *defaults # 合并 defaults 的所有内容 test: database: myapp_test <<: *defaults port: 5433 # 覆盖默认值
解析结果等价于:
development: database: myapp_dev adapter: postgres host: localhost port: 5432 test: database: myapp_test adapter: postgres host: localhost port: 5433 # 覆盖了 defaults 的 port
更简洁的列表引用写法:
- &showell Steve - Clark - Brian - *showell # 引用锚点,值为 Steve # 结果:[Steve, Clark, Brian, Steve]
3. 多文档:用 --- 分隔
YAML 1.2 规范原生支持在一个文件中写多个独立文档,用 --- 作为分隔符。
# 文档1:默认配置 spring: application: name: order-service datasource: url: jdbc:mysql://localhost:3306/mydb --- # 文档2:开发环境 spring: profiles: dev datasource: url: jdbc:mysql://dev-db:3306/mydb --- # 文档3:生产环境 spring: profiles: pro datasource: url: jdbc:mysql://prod-db:3306/mydb
在 Spring Boot 中,通过 spring.profiles.active 指定启用哪个文档,这是管理多环境配置的标准做法。
用 Python 加载多文档:
import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
documents = list(yaml.safe_load_all(f)) # 返回生成器,转列表
print(len(documents)) # 输出: 3
print(documents[0]['spring']['application']['name']) # 输出: order-service
六、YAML 类型标签:!! 显式指定类型
当 YAML 的自动类型推断不够用时,可以用 !! 显式指定类型:
| 标签 | 含义 | 示例 |
|---|---|---|
!!str | 字符串 | value: !!str 123 → "123"(不是数字) |
!!int | 整数 | value: !!int 123 |
!!float | 浮点数 | value: !!float 3.14 |
!!bool | 布尔值 | value: !!bool yes |
!!timestamp | 日期时间 | value: !!timestamp 2026-06-16T10:24:00+08:00 |
!!null | 空值 | value: !!null ~ |
典型应用:防止 1d6 被解析为数字
# 不加标签:YAML 可能把 1d6 解析为特殊值 damage: 1d6 # 加标签:强制作为字符串 damage: !!str 1d6
七、YAML 真实案例:五大 DevOps 场景
案例 1:Docker Compose(最常见的 YAML 文件)
version: '3' services: web: image: nginx:latest ports: - "80:80" volumes: - ./html:/usr/share/nginx/html db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: example volumes: - db_data:/var/lib/mysql volumes: db_data:
案例 2:Kubernetes Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
案例 3:Spring Boot 多环境配置
# 默认配置(所有环境共享)
spring:
application:
name: order-service
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
connection-timeout: 30000
maximum-pool-size: 10
---
# 开发环境
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/mydb_dev
username: root
password: dev123
---
# 生产环境
spring:
profiles: pro
datasource:
url: jdbc:mysql://prod-db:3306/mydb_pro
username: ${DB_USER}
password: ${DB_PASSWORD}案例 4:GitHub Actions 工作流
name: CI Pipeline on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install dependencies run: npm install - name: Run tests run: npm test - name: Build run: npm run build
案例 5:Ansible Playbook
--- - name: Install Nginx hosts: webservers become: yes tasks: - name: Install Nginx package apt: name: nginx state: present - name: Start Nginx service service: name: nginx state: started
八、YAML vs JSON vs TOML:到底选哪个?
| 对比维度 | YAML | JSON | TOML |
|---|---|---|---|
| 注释 | ✅ 支持 | ❌ 不支持 | ✅ 支持 |
| 缩进层级 | ✅ 原生支持 | ❌ 无 | ❌ 无 |
| 锚点引用 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 多文档 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 |
| 日期时间 | ISO 8601 | ❌ 无原生类型 | RFC 3339 |
| 学习曲线 | 中等(缩进易出错) | 简单 | 简单 |
| 适用场景 | 复杂配置、运维 | API 数据交换 | 简单配置文件 |
| 主流工具支持 | Docker/K8s/Ansible/Spring | 几乎所有 | Python/Rust/Cargo |
核心结论:
如果你在写配置文件(尤其是 DevOps 场景):选 YAML,没有第二选择
如果你在做 API 数据交换:选 JSON,universal standard
如果你在写简单的项目配置(如 pyproject.toml):选 TOML,更简洁不易出错
九、YAML 常见陷阱与避坑指南
| 陷阱 | 错误示例 | 正确做法 |
|---|---|---|
| 用 Tab 缩进 | name:(前面是Tab) | 永远只用空格,建议2空格 |
| 冒号后无空格 | name:Alice | name: Alice |
| 布尔值大小写错误 | enabled: True |
只能用 true/false(全小写) |
| 字符串看起来像数字 | id: 0123 → 被解析为八进制 |
用引号包起来:id: "0123" |
| 列表项缩进不一致 | 有的2空格有的4空格 | 同一列表必须统一缩进 |
| 多文档只加载第一个 |
用 yaml.load() 只拿到第一个文档 |
用 yaml.safe_load_all() 加载全部 |
| 特殊字符未引号包裹 | key: value: test → 冒号冲突 | key: "value: test" |
十、用 Python 读写 YAML
import yaml
# 读取 YAML 文件
with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) # 单个文档
# data = list(yaml.safe_load_all(f)) # 多文档
print(data['spring']['datasource']['url'])
# 写入 YAML 文件
data = {
'name': 'myapp',
'version': '1.0.0',
'features': ['auth', 'logging', 'cache']
}
with open('output.yaml', 'w', encoding='utf-8') as f:
yaml.safe_dump(data, f, default_flow_style=False, indent=2, allow_unicode=True)安装方式:pip install pyyaml
注意:始终使用 safe_load 而非 load,防止 YAML 注入攻击。
十一、相关工具推荐
JSON转YAML工具:https://www.fuwa.org/tools/json-to-yaml.html
YAML转JSON工具:https://www.fuwa.org/tools/yaml-to-json.html
总结
YAML 的本质,是用最少的符号表达最丰富的数据结构。 它不追求花哨,只追求一件事:让人一眼就能看懂,让机器一解析就不会出错。
从 key: value 的简单键值对,到 &anchor / *alias 的锚点引用;从 | 保留换行的多行字符串,到 --- 分隔的多文档;从 Docker Compose 到 Kubernetes 部署清单——YAML 把配置文件该有的能力全部给齐了,而且给得优雅。
如果你正在进入 DevOps 领域,或者需要为项目选一个配置文件格式,YAML 是你绑不开的第一课。记住五条铁律,避开常见陷阱,你就已经超过了 80% 的 YAML 使用者。
相关工具
YAML转JSON工具
JSON转YAML工具
版权及免责申明:本文由@fuwa原创发布。该文章观点仅代表作者本人,不代表本站立场。本站不承担任何相关法律责任。
如若转载,请注明出处:https://www.fuwa.org/tutorials/what-is-yaml.html

