YAML vs JSON:语法对比与互转技巧

YAML 和 JSON 是现代开发中最常用的两种数据序列化格式。JSON 在 API 通信中占据主导,而 YAML 则是配置文件的首选。本文将深入对比两者的语法差异、各自优势,并教你如何在它们之间灵活转换。

基础语法对比

先通过一个实际例子直观感受两种格式的差异:

YAML
# 用户信息配置
name: 张三
age: 28
active: true
address: null
skills:
  - JavaScript
  - Python
  - Go
contact:
  email: zhangsan@example.com
  phone: "138-0000-0000"
JSON
{
  "name": "张三",
  "age": 28,
  "active": true,
  "address": null,
  "skills": [
    "JavaScript",
    "Python",
    "Go"
  ],
  "contact": {
    "email": "zhangsan@example.com",
    "phone": "138-0000-0000"
  }
}

核心差异总结

特性YAMLJSON
分隔符缩进(空格)花括号 {} 和方括号 []
引号字符串通常不需要引号键名和字符串必须双引号
注释✅ 支持(#❌ 不支持
多行字符串✅ 支持(|>❌ 只能用 \n 转义
锚点/引用✅ 支持(&*❌ 不支持
多文档✅ 支持(--- 分隔)❌ 不支持
数据类型自动推断(可能有歧义)明确的类型标记
可读性⭐⭐⭐ 更简洁⭐⭐ 结构清晰但冗长
解析性能较慢更快
主要用途配置文件API 通信、数据交换

YAML 独有特性

1. 注释

YAML 支持行内和单行注释,这是它在配置文件领域碾压 JSON 的主要原因:

# 数据库配置
database:
  host: localhost      # 开发环境使用本地
  port: 5432           # PostgreSQL 默认端口
  name: myapp_dev
  # password: secret   # 已移至环境变量

2. 多行字符串

YAML 提供两种多行字符串语法:

# | (Literal Block): 保留换行符
description: |
  这是第一行
  这是第二行
  这是第三行

# 等价 JSON: "这是第一行\n这是第二行\n这是第三行\n"

# > (Folded Block): 换行变为空格
summary: >
  这是一段很长的文本,
  会被折叠成一行,
  换行符变为空格。

# 等价 JSON: "这是一段很长的文本, 会被折叠成一行, 换行符变为空格。\n"

3. 锚点与引用

YAML 的锚点(&)和引用(*)可以复用配置,避免重复:

# 定义默认配置锚点
defaults: &defaults
  adapter: postgres
  host: localhost
  port: 5432

# 引用并覆盖
development:
  database:
    <<: *defaults       # 合并 defaults 的所有键值
    name: myapp_dev

production:
  database:
    <<: *defaults
    host: db.example.com  # 覆盖 host
    name: myapp_prod
💡 提示:锚点和引用在大型配置文件中非常有用,比如 Docker Compose 的服务定义、CI/CD 流水线配置等。

4. 多文档支持

# 第一个文档
---
name: app-frontend
version: 2.1.0
# 第二个文档
---
name: app-backend
version: 3.0.1

YAML 的常见陷阱

类型推断歧义

YAML 自动推断数据类型,这可能导致意外的结果:

# 这些值的实际类型可能出乎意料
version: 1.0        # 浮点数 1.0,不是字符串 "1.0"
country: NO         # 布尔值 false(挪威国家代码!)
zip: 01onal        # 八进制数(某些解析器)
time: 12:30         # 某些解析器会解析为数字 750

# 解决方案:用引号强制字符串
version: "1.0"
country: "NO"
zip: "01234"
⚠️ 挪威问题:这是 YAML 社区著名的 bug。在 YAML 1.1 中,NOnooff 会被解析为布尔值 false。YAML 1.2 修复了部分问题,但仍需注意。建议敏感值始终加引号。

缩进敏感

# ❌ 错误:混用 Tab 和空格
database:
	host: localhost   # Tab 缩进!YAML 不允许

# ✅ 正确:统一使用空格(推荐 2 个)
database:
  host: localhost
  port: 5432

互转方法

YAML → JSON(Python)

import yaml
import json

with open("config.yaml") as f:
    data = yaml.safe_load(f)

json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)

JSON → YAML(Python)

import yaml
import json

with open("data.json") as f:
    data = json.load(f)

yaml_str = yaml.dump(data, allow_unicode=True, default_flow_style=False)
print(yaml_str)

命令行转换

# 使用 yq 工具(需安装)
# YAML → JSON
yq -o=json config.yaml

# JSON → YAML
yq -P data.json

# 使用 Python one-liner
python3 -c "import sys,yaml,json; print(json.dumps(yaml.safe_load(open(sys.argv[1])),indent=2))" config.yaml

如何选择?

  • 选 YAML:人工编辑的配置文件、需要注释、Docker Compose、Kubernetes、GitHub Actions
  • 选 JSON:API 响应/请求、程序间数据交换、package.json、需要严格类型
  • 选 TOML:简单的配置文件(如 Cargo.toml、pyproject.toml)
💡 实际建议:在同一个项目中保持一致。如果团队习惯 YAML 就统一用 YAML,习惯 JSON 就统一用 JSON。混用反而增加认知负担。

🛠️ 在线 YAML 格式化与 JSON 互转工具

打开 YAML 工具 →

延伸阅读