← 返回博客

JSON 转 YAML 完全指南

2026-04-18 · 5 分钟阅读

JSON 与 YAML:语法对比

YAML(YAML Ain't Markup Language)和 JSON 都是数据序列化格式,YAML 实际上是 JSON 的超集——所有有效的 JSON 都是有效的 YAML。但两者的常用写法差异很大:YAML 使用缩进表示层级,不需要花括号和引号,支持注释,更面向人类阅读;JSON 则使用花括号和引号,结构严格,无注释,更适合机器解析和传输。

两种格式表达同样的数据:

// JSON
{
  "name": "Alice",
  "age": 30,
  "roles": ["admin", "editor"],
  "address": {
    "city": "Beijing",
    "country": "China"
  }
}

# YAML
name: Alice
age: 30
roles:
  - admin
  - editor
address:
  city: Beijing
  country: China

JSON 转 YAML 的规则

理解转换规则有助于手动调整和验证转换结果:JSON 对象({})变为 YAML 的键值对形式,用缩进表示嵌套;JSON 数组([])变为 YAML 的列表项,每项前加 - ;字符串不一定需要引号(纯数字字符串、含特殊字符的字符串例外);数字、布尔值、null 直接写,不加引号;注释在 YAML 中用 # 表示,JSON 中不支持注释。

需要特别注意的转换陷阱:在 YAML 中,yes/no/true/false/on/off 都是布尔值,如果你的 JSON 字符串键恰好是这些词,转换为 YAML 后需要加引号。纯数字的 JSON 字符串(如 "123")转为 YAML 时必须保持引号,否则会被解析为整数。

命令行工具转换

yq 是专为 YAML 设计的命令行工具(类似 JSON 的 jq),支持 JSON 和 YAML 之间的互转:

# 安装 yq / Install yq
brew install yq  # macOS
# 或 / or: snap install yq

# JSON 转 YAML / JSON to YAML
yq -p json -o yaml input.json > output.yaml

# YAML 转 JSON / YAML to JSON
yq -p yaml -o json input.yaml > output.json

# 从标准输入转换 / Convert from stdin
cat data.json | yq -p json -o yaml

# 使用 python 内置模块转换
# Convert using Python built-in modules
python3 -c "import sys,json,yaml; yaml.dump(json.load(sys.stdin), sys.stdout, allow_unicode=True)" < input.json

# 使用 nodejs 转换
# Convert using Node.js
node -e "const y=require('js-yaml'); const j=require('fs').readFileSync(0,'utf8'); process.stdout.write(y.dump(JSON.parse(j)));"

各语言的代码实现

# Python
import json
import yaml

# JSON 字符串转 YAML / JSON string to YAML
def json_to_yaml(json_str):
    data = json.loads(json_str)
    return yaml.dump(data, allow_unicode=True, default_flow_style=False)

# YAML 字符串转 JSON / YAML string to JSON
def yaml_to_json(yaml_str):
    data = yaml.safe_load(yaml_str)
    return json.dumps(data, ensure_ascii=False, indent=2)

// JavaScript (使用 js-yaml 库)
// JavaScript (using js-yaml library)
import yaml from 'js-yaml';

// JSON 对象转 YAML 字符串
function jsonToYaml(obj) {
  return yaml.dump(obj, { indent: 2 });
}

// YAML 字符串转 JSON 对象
function yamlToJson(yamlStr) {
  return yaml.load(yamlStr);
}

// Go (使用 gopkg.in/yaml.v3)
// Go (using gopkg.in/yaml.v3)
import (
    "encoding/json"
    "gopkg.in/yaml.v3"
)

func jsonToYaml(jsonBytes []byte) ([]byte, error) {
    var obj interface{}
    if err := json.Unmarshal(jsonBytes, &obj); err != nil {
        return nil, err
    }
    return yaml.Marshal(obj)
}

YAML 在 DevOps 工具中的应用

YAML 在 DevOps 生态中无处不在,理解 JSON 与 YAML 的转换关系,有助于在这些工具之间灵活迁移配置:Kubernetes:所有资源配置(Deployment、Service、ConfigMap)都使用 YAML 格式,但 Kubernetes API 实际上接受 JSON,kubectl 会自动转换。GitHub Actions:工作流文件是 YAML 格式,理解其数据结构有助于调试复杂的工作流配置。Ansible:Playbook 和 inventory 文件使用 YAML,变量可以用 JSON 格式的字符串传递。Docker Composedocker-compose.yml 是 YAML 格式。

# Kubernetes Deployment(YAML,等效于 JSON 格式的 API 调用)
# Kubernetes Deployment (YAML, equivalent to JSON-format API call)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
        - name: app
          image: my-app:latest
          ports:
            - containerPort: 8080

YAML 特有功能:锚点和引用

YAML 比 JSON 多出一些独特功能,其中最实用的是锚点(Anchor)和引用(Alias):使用 &anchor_name 定义一个锚点,用 *anchor_name 在其他地方引用它,从而避免重复定义。这在配置文件中特别有用——比如多个服务共享相同的基础配置:

YAML 还支持多行字符串(使用 | 保留换行,使用 > 折叠换行)、空文档分隔符(---)可以在一个文件中包含多个 YAML 文档(JSON 不支持这些特性)。这些功能在从 JSON 转换为 YAML 后可以手动添加,以充分利用 YAML 的表达能力。

# YAML 锚点和引用示例 / YAML anchor and alias example
defaults: &defaults
  timeout: 30
  retries: 3
  logLevel: info

development:
  <<: *defaults  # 继承 defaults 的所有字段 / Inherit all defaults fields
  debug: true
  logLevel: debug  # 覆盖继承的字段 / Override inherited field

production:
  <<: *defaults
  replicas: 10
  ssl: true

转换时的常见陷阱

布尔值陷阱:YAML 1.1 将 yes/no/on/off/true/false 都解析为布尔值,但 YAML 1.2(更严格)只有 true/false。确保使用的 YAML 库版本支持的规范,并对可能被误解析的字符串加引号。

八进制数字陷阱:在 YAML 1.1 中,以 0 开头的数字被解析为八进制(如 010 被解析为 8)。如果 JSON 中有类似格式的字符串 ID(如 "0123456789"),转换后要确保它们带引号。

空字符串陷阱:JSON 的 "" 在 YAML 中需要写成 ""'',不能省略引号(因为省略引号的空值在 YAML 中被解析为 null)。

缩进敏感性:YAML 对缩进极为敏感,混用 Tab 和空格会导致解析错误。始终使用空格(推荐 2 个空格)进行缩进。

立即免费使用相关工具

免费使用 →