YAML 的语法规则由它的设计目标决定:让人类轻松读写。它用缩进表达层级,用符号简化结构,但它对格式的细节很敏感。
以下从基础到进阶,把 YAML 的规则拆解清楚。
一、基础规则:大小写敏感 + 缩进
规则 1:大小写敏感
YAML 区分大小写。Server 和 server 是两个不同的键。
规则 2:缩进用空格,不用 Tab
YAML 强制使用空格进行缩进。Tab 会导致解析错误。Spring Boot 的 YAML 解析器会直接报错,不会自动转换。
yaml
# 正确:用两个空格缩进
server:
port: 8080
# 错误:Tab 缩进(解析失败)
server:
port: 8080
规则 3:相同层级的元素左对齐
yaml
server:
port: 8080
context-path: /api # 与 port 左对齐
database:
url: jdbc:mysql://... # 与 server 左对齐(不同父节点)
规则 4:: 后面必须有空格
键值对中,冒号后面必须加一个空格。这是语法要求。
yaml
# 正确
name: myapp
# 错误(缺少空格)
name:myapp
二、数据结构表达
1. 对象(Map / 字典)
通过缩进表示层级。
yaml
server:
port: 8080
timeout: 30
host: localhost
等价于 JSON:
json
{
"server": {
"port": 8080,
"timeout": 30,
"host": "localhost"
}
}
内联写法:
yaml
server: { port: 8080, timeout: 30, host: localhost }
2. 数组(List / 序列)
用 - 加空格表示列表项。
yaml
servers:
- server1
- server2
- server3
等价于 JSON:
json
{
"servers": ["server1", "server2", "server3"]
}
内联写法:
yaml
servers: [server1, server2, server3]
3. 对象列表
数组中的每个元素是一个对象。
yaml
users:
- name: zhangsan
age: 25
email: zhangsan@example.com
- name: lisi
age: 30
email: lisi@example.com
等价于 JSON:
json
{
"users": [
{ "name": "zhangsan", "age": 25, "email": "zhangsan@example.com" },
{ "name": "lisi", "age": 30, "email": "lisi@example.com" }
]
}
4. 嵌套组合
yaml
app:
name: myapp
version: 1.0
features:
cache: true
logging: false
servers:
- prod-server
- dev-server
security:
enabled: true
roles:
- admin
- user
三、纯量(Scalar)数据类型
1. 字符串
默认不加引号。包含特殊字符时用引号包裹。
yaml
# 普通字符串
name: myapp
# 包含空格
description: This is my application
# 包含特殊字符(需要引号)
message: 'Hello: World' # 包含冒号
path: 'C:\Users\admin' # 包含反斜杠
quote: "He said: 'Hello'" # 包含单引号
单引号 vs 双引号:
yaml
# 单引号:原样输出,不解析转义
single: 'Hello \n World' # 输出:Hello \n World
# 双引号:解析转义字符
double: "Hello \n World" # 输出:Hello(换行) World
2. 多行字符串
保留换行(|):
yaml
description: |
This is the first line.
This is the second line.
This is the third line.
去掉末尾换行(>-):
yaml
description: >-
This line will be folded.
This is the second line.
# 最终拼接为一行:This line will be folded. This is the second line.
3. 数字
yaml
integer: 100
float: 3.14
negative: -50
exponential: 1.2e+5
4. 布尔值
支持多种写法:
yaml
enabled: true # 真
disabled: false # 假
# 也支持以下写法
on: true
off: false
yes: true
no: false
5. Null
yaml
value: null
value: ~ # 等价写法
6. 日期和时间
yaml
date: 2024-01-01
datetime: 2024-01-01T10:30:00+08:00
四、高级语法
1. 注释
用 # 添加注释。注释可以单独占一行,也可以跟在值后面。
yaml
# 服务器配置
server:
port: 8080 # 监听端口
timeout: 30 # 超时时间(秒)
2. 锚点(&)与引用(*)
复用配置片段。
yaml
defaults: &defaults
timeout: 30
retries: 3
server1:
<<: *defaults
host: server1.example.com
server2:
<<: *defaults
host: server2.example.com
timeout: 60 # 覆盖默认值
解析后,server1 包含 timeout: 30、retries: 3、host: server1.example.com。server2 的 timeout 被覆盖为 60。
3. 多文档块(---)
一个 YAML 文件中可以包含多个文档,用 --- 分隔。
yaml
# 第一个文档
spring:
profiles: dev
datasource:
url: jdbc:h2:mem:dev
---
# 第二个文档
spring:
profiles: prod
datasource:
url: jdbc:mysql://prod:3306/db
Spring Boot 利用这个机制实现多 Profile 配置(配合 spring.config.activate.on-profile)。
4. 强制类型转换
yaml
string_value: !!str 100
integer_value: !!int "100"
boolean_value: !!bool "true"
5. 空值标记
yaml
empty_list: [] # 空数组
empty_map: {} # 空对象
null_value: null # 空值
五、Spring Boot 中的特殊规则
1. @Value 注入列表
yaml
servers:
- server1
- server2
java
@Value("${servers}")
private List<String> servers; // 自动拆分
2. @ConfigurationProperties 绑定
yaml
app:
name: myapp
timeout: 30
features:
cache: true
logging: false
java
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private int timeout;
private Map<String, Boolean> features;
}
3. 配置文件加载顺序中的规则
YAML 和 properties 可以共存。同一个键在两种格式中都出现时,properties 优先级更高(先加载 YAML,后加载 properties,后者覆盖前者)。
六、常见错误
错误 1:缩进不一致
yaml
# 错误(2 空格和 4 空格混用)
server:
port: 8080
timeout: 30
错误 2:冒号后缺少空格
yaml
# 错误
name:myapp
错误 3:使用 Tab
yaml
# 错误(使用了 Tab)
server:
port: 8080
错误 4:列表项缩进不对
yaml
# 错误(列表项未左对齐)
servers:
- server1
- server2
错误 5:字符串中包含特殊字符未加引号
yaml
# 错误(冒号在字符串中)
description: this is: a test
# 正确(加引号)
description: 'this is: a test'
错误 6:注释前缺少空格
yaml
# 正确
port: 8080 # 监听端口
# 错误(# 前无空格,但 YAML 仍能解析,是风格问题)
port: 8080# 监听端口
七、总结
YAML 的关键规则:
| 规则 | 说明 |
|---|---|
| 缩进 | 只用空格,不用 Tab,相同层级左对齐 |
| 冒号 | 键值对中冒号后必须有空格 |
| 列表 | - 后必须有空格 |
| 类型 | 自动推断,必要时用引号控制 |
| 注释 | # 开头 |
| 多文档 | --- 分隔 |
| 引用 | & 定义锚点,* 引用 |
YAML 的设计目标是让人类能轻松读写配置。缩进替代了 XML 的闭合标签和 JSON 的括号,这让它高度可读,也意味着任何格式错误都会导致解析失败。写配置时记住两点:缩进保持一致,冒号后面加空格,就能避免 90% 的格式问题。