YAML 到 JSON 的转换是开发者日常面对的最常见数据格式任务之一。无论你管理 Kubernetes 清单、Docker Compose 文件、CI/CD 管道还是应用配置,都经常需要在 YAML 和 JSON 之间转换。YAML 以其可读性强、基于缩进的语法著称,而 JSON 则主导 API 和程序化数据交换。本综合指南涵盖了 YAML 到 JSON 转换器工具、解析过程、四种语言的代码示例、常见陷阱和最佳实践。如果你需要快速进行 YAML 到 JSON 的在线转换,请试用我们下方的免费工具。
立即试用我们的免费在线 YAML 到 JSON / JSON 到 YAML 转换工具。
什么是 YAML?
YAML(YAML Ain't Markup Language)是一种人类友好的数据序列化语言,广泛用于配置文件和数据交换。YAML 解析器读取基于缩进的结构,将其转换为字典、列表和标量等原生数据结构。
YAML 使用空白缩进(仅限空格,不允许制表符)来表示结构,使其视觉上整洁易读。它支持标量类型(字符串、整数、浮点数、布尔值、null)、序列(数组/列表)和映射(字典/对象)。高级功能包括锚点和别名用于数据重用、多行字符串的块标量(| 保持原样,> 折叠),以及用 --- 分隔的多文档文件。YAML 语法被设计为 JSON 的超集,即每个有效的 JSON 文档也是有效的 YAML。
YAML 是 Kubernetes 清单、Ansible playbook、Docker Compose 文件、GitHub Actions 工作流、Swagger/OpenAPI 规范、Spring Boot 配置等众多 DevOps 和云原生工具的首选格式。其相比 JSON 的可读性优势使其成为人类频繁编辑的文件的首选,而 JSON 仍是机器间通信和 API 的首选。
YAML 与 JSON:关键区别
了解 YAML 和 JSON 之间的区别有助于选择正确的格式并避免转换陷阱。以下是详细对比:
| 特性 | YAML | JSON |
|---|---|---|
| 语法 | 基于缩进,无需括号或大括号 | 由括号和大括号分隔 |
| 注释 | 支持 # 注释 | 不支持注释 |
| 数据类型 | 字符串、整数、浮点、布尔、null、日期、二进制 | 字符串、数字、布尔、null、数组、对象 |
| 多行字符串 | 块标量:|(保持原样)和 >(折叠) | 必须使用 \n 转义 |
| 锚点和别名 | 支持 & 和 * 数据重用 | 不支持 |
| 可读性 | 高度可读,标点符号少 | 引号和括号较多 |
| 解析速度 | 较慢(缩进敏感) | 较快(语法简单) |
YAML 到 JSON 转换的工作原理
使用 YAML 到 JSON 转换器时,工具会执行多步解析和序列化过程。
第 1 步:词法分析(分词) — YAML 解析器逐字符扫描原始 YAML 文本,识别缩进级别、键值分隔符(:)、序列指示符(-)、块标量指示符(|、>)、锚点(&)、别名(*)和标量值等标记。
第 2 步:解析(AST 构建) — 标记被组装成代表层次结构的抽象语法树(AST)。映射成为对象节点,序列成为数组节点,标量成为叶节点。
第 3 步:组合(原生数据结构) — AST 被转换为编程语言的原生数据结构。此时发生隐式类型转换:true/false/yes/no 变为布尔值,未引用的数字变为整数或浮点数。
第 4 步:JSON 序列化 — 原生数据结构被序列化为 JSON 文本。YAML 注释被丢弃,锚点和别名被完全展开。
YAML 到 JSON 代码示例
JavaScript / Node.js (js-yaml)
js-yaml 是最流行的 JavaScript YAML 解析器。使用 yaml.load() 解析 YAML,结合 JSON.stringify() 实现完整的 YAML 到 JSON 转换:
// ===== YAML to JSON (Node.js) =====
const yaml = require('js-yaml');
const fs = require('fs');
// Parse YAML string to JavaScript object
const yamlString = `
server:
host: localhost
port: 8080
ssl: true
database:
name: myapp
replicas:
- host: db1.example.com
port: 5432
- host: db2.example.com
port: 5432
# Connection pool settings
pool:
min: 5
max: 20
`;
const data = yaml.load(yamlString);
const json = JSON.stringify(data, null, 2);
console.log(json);
// {
// "server": {
// "host": "localhost",
// "port": 8080,
// "ssl": true
// },
// "database": {
// "name": "myapp",
// "replicas": [
// { "host": "db1.example.com", "port": 5432 },
// { "host": "db2.example.com", "port": 5432 }
// ],
// "pool": { "min": 5, "max": 20 }
// }
// }
// ===== JSON to YAML =====
const jsonData = { name: 'app', version: '2.0', features: ['auth', 'logging'] };
const yamlOutput = yaml.dump(jsonData, { indent: 2 });
console.log(yamlOutput);
// name: app
// version: '2.0'
// features:
// - auth
// - logging
// ===== Read YAML file and convert to JSON =====
const fileContent = fs.readFileSync('config.yaml', 'utf8');
const config = yaml.load(fileContent);
fs.writeFileSync('config.json', JSON.stringify(config, null, 2));
// ===== Handle multi-document YAML =====
const multiDoc = `
---
name: doc1
---
name: doc2
`;
const docs = yaml.loadAll(multiDoc);
console.log(JSON.stringify(docs, null, 2));
// [{ "name": "doc1" }, { "name": "doc2" }]Python (PyYAML)
Python 的 PyYAML 是标准的 YAML 解析器。始终使用 yaml.safe_load() 以防止不受信任的 YAML 执行任意代码:
import yaml
import json
# ===== YAML to JSON =====
yaml_string = """
server:
host: localhost
port: 8080
ssl: true
database:
name: myapp
replicas:
- host: db1.example.com
port: 5432
- host: db2.example.com
port: 5432
pool:
min: 5
max: 20
"""
# Always use safe_load (prevents arbitrary code execution)
data = yaml.safe_load(yaml_string)
json_output = json.dumps(data, indent=2, ensure_ascii=False)
print(json_output)
# ===== JSON to YAML =====
json_string = '{"name": "app", "version": "2.0", "features": ["auth", "logging"]}'
json_data = json.loads(json_string)
yaml_output = yaml.dump(json_data, default_flow_style=False, allow_unicode=True)
print(yaml_output)
# ===== File conversion =====
# YAML file to JSON file
with open('config.yaml', 'r') as yf:
config = yaml.safe_load(yf)
with open('config.json', 'w') as jf:
json.dump(config, jf, indent=2)
# JSON file to YAML file
with open('data.json', 'r') as jf:
data = json.load(jf)
with open('data.yaml', 'w') as yf:
yaml.dump(data, yf, default_flow_style=False)
# ===== Handle multi-document YAML =====
multi_yaml = """
---
name: doc1
type: config
---
name: doc2
type: data
"""
docs = list(yaml.safe_load_all(multi_yaml))
print(json.dumps(docs, indent=2))
# ===== Preserve key order (Python 3.7+) =====
# dict maintains insertion order by default
ordered = yaml.safe_load(yaml_string)
print(json.dumps(ordered, indent=2)) # keys stay in YAML orderBash / CLI (yq, python 单行命令)
命令行 YAML 到 JSON 转换中,yq 是最高效的工具。也可以用 Python 或 Ruby 单行命令快速转换:
# ===== yq: YAML processor (like jq for YAML) =====
# Convert YAML file to JSON
yq -o=json config.yaml
# Convert YAML to JSON and save to file
yq -o=json config.yaml > config.json
# Convert JSON to YAML
yq -P config.json
# Convert JSON to YAML and save
yq -P config.json > config.yaml
# Extract a specific field from YAML as JSON
yq -o=json '.server.port' config.yaml
# ===== Python one-liner =====
# YAML to JSON (stdin)
cat config.yaml | python3 -c \
'import sys,yaml,json; json.dump(yaml.safe_load(sys.stdin),sys.stdout,indent=2)'
# YAML to JSON (file)
python3 -c \
'import yaml,json; print(json.dumps(yaml.safe_load(open("config.yaml")),indent=2))'
# JSON to YAML
cat data.json | python3 -c \
'import sys,yaml,json; print(yaml.dump(json.load(sys.stdin),default_flow_style=False))'
# ===== Ruby one-liner =====
ruby -ryaml -rjson -e 'puts JSON.pretty_generate(YAML.load($stdin.read))' < config.yaml
# ===== Pipe YAML from curl to JSON =====
curl -s https://raw.githubusercontent.com/example/repo/main/config.yaml | \
yq -o=json
# ===== Validate YAML before converting =====
yamllint config.yaml && yq -o=json config.yamlGo (gopkg.in/yaml.v3)
Go 语言中,gopkg.in/yaml.v3 包提供强大的 YAML 解析支持:
package main
import (
"encoding/json"
"fmt"
"log"
"gopkg.in/yaml.v3"
)
func main() {
// YAML input string
yamlData := []byte(`
server:
host: localhost
port: 8080
ssl: true
database:
name: myapp
replicas:
- host: db1.example.com
port: 5432
- host: db2.example.com
port: 5432
`)
// Parse YAML into interface{}
var data interface{}
err := yaml.Unmarshal(yamlData, &data)
if err != nil {
log.Fatalf("YAML parse error: %v", err)
}
// Convert map[string]interface{} keys for JSON compatibility
data = convertMapKeys(data)
// Marshal to JSON
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
log.Fatalf("JSON marshal error: %v", err)
}
fmt.Println(string(jsonData))
}
// convertMapKeys recursively converts map[interface{}]interface{}
// to map[string]interface{} for JSON compatibility
func convertMapKeys(v interface{}) interface{} {
switch v := v.(type) {
case map[string]interface{}:
result := make(map[string]interface{})
for key, val := range v {
result[key] = convertMapKeys(val)
}
return result
case []interface{}:
for i, val := range v {
v[i] = convertMapKeys(val)
}
return v
default:
return v
}
}JSON 到 YAML 转换
反方向的 JSON 到 YAML 转换同样重要。当你从 API 接收 JSON 需要存储为 YAML 配置时,或想让 JSON 更具可读性时,这是最佳方案。
注意:注释会丢失。将带注释的 YAML 转为 JSON 再转回 YAML,所有注释将永久丢失。要保留注释,请使用 ruamel.yaml 等专用工具。
最佳实践:(1) 使用 2 空格缩进。(2) 避免流式风格。(3) 引用可能被误解的字符串。(4) 用 YAML 验证器验证输出。
常见 YAML 陷阱与边缘情况
YAML 的灵活性引入了一些坑点。了解这些陷阱有助于编写正确的 YAML:
制表符与空格 — YAML 禁止使用制表符缩进。始终配置编辑器在 YAML 文件中插入空格。
布尔值陷阱 — YAML 1.1 将 yes、no、on、off 等解释为布尔值。国家代码 NO(挪威)会变成 false。务必给可能被误读的字符串加引号。
# The YAML boolean trap - these all become true or false in JSON!
# YAML 1.1 boolean values (case-insensitive):
is_active: yes # → true
is_active: no # → false
is_active: on # → true
is_active: off # → false
is_active: y # → true
is_active: n # → false
is_active: true # → true
is_active: false # → false
# Real-world problems:
countries:
- US # string "US" ✓
- GB # string "GB" ✓
- NO # boolean false ✗ (Norway disappears!)
- FR # string "FR" ✓
# Fix: always quote ambiguous values
countries:
- "US"
- "GB"
- "NO" # string "NO" ✓
- "FR"
# Version numbers are also problematic:
version: 1.0 # → float 1 (not string "1.0")
version: "1.0" # → string "1.0" ✓多行字符串 — | 保持换行,> 将换行替换为空格。截断指示符控制尾部换行。
# YAML multiline string variants
# Literal block scalar (|) - preserves newlines
description: |
This is line one.
This is line two.
This is line three.
# JSON: "This is line one.\nThis is line two.\nThis is line three.\n"
# Folded block scalar (>) - replaces newlines with spaces
description: >
This is a long
paragraph that will
be folded into one line.
# JSON: "This is a long paragraph that will be folded into one line.\n"
# Chomping indicators:
keep_trailing: |+ # Keep ALL trailing newlines
text
strip_trailing: |- # Strip ALL trailing newlines
text
clip_trailing: | # Keep exactly ONE trailing newline (default)
text特殊字符 — 值中的冒号、井号、括号和大括号必须加引号以避免解析错误。
锚点和别名 — JSON 转换时完全展开,可能增加文件大小。循环别名可能导致无限循环。
# YAML anchors and aliases
# Define an anchor with &
defaults: &default_settings
adapter: postgres
host: localhost
port: 5432
# Reuse with alias *
development:
database:
<<: *default_settings # Merge key: inherits all defaults
database: myapp_dev
production:
database:
<<: *default_settings # Same defaults
database: myapp_prod
host: db.production.com # Override specific values
# After JSON conversion (anchors fully expanded):
# {
# "defaults": { "adapter": "postgres", "host": "localhost", "port": 5432 },
# "development": {
# "database": {
# "adapter": "postgres", "host": "localhost",
# "port": 5432, "database": "myapp_dev"
# }
# },
# "production": {
# "database": {
# "adapter": "postgres", "host": "db.production.com",
# "port": 5432, "database": "myapp_prod"
# }
# }
# }数字和日期解释 — 1.0 变成浮点数 1 而非字符串 "1.0"。如需字符串,请加引号。
YAML 最佳实践
遵循以下最佳实践,编写干净、可维护的 YAML:
一致的缩进 — 全文使用 2 个空格缩进,与 Kubernetes 和 Docker Compose 的惯例一致。
防御性引用字符串 — 有疑问时就加引号。布尔值、数字、null 和日期格式的值都应该引用。
避免布尔值陷阱 — 特别注意国家代码、开关值和简短回答。使用 linter 自动检查。
Schema 验证 — 使用 JSON Schema 验证 YAML 结构。
使用 yamllint — 在 CI/CD 管道中集成 yamllint 检查常见问题。
# .yamllint.yml configuration example
---
extends: default
rules:
line-length:
max: 120
allow-non-breakable-words: true
indentation:
spaces: 2
indent-sequences: true
comments:
min-spaces-from-content: 1
truthy:
check-keys: true
allowed-values: ['true', 'false']
document-start:
present: true
trailing-spaces: enable
new-line-at-end-of-file: enable
# Run yamllint:
# yamllint .
# yamllint config.yaml
# yamllint -d "{extends: default}" config.yaml明智地使用注释 — 记住注释在转为 JSON 时会丢失,关键信息也应保存在外部文档中。
常见问题
YAML 和 JSON 有什么区别?
YAML 和 JSON 都是数据序列化格式,但有几个关键区别。YAML 使用基于缩进的语法,支持注释和高级功能(锚点、别名、多行字符串)。JSON 使用括号分隔,不支持注释,数据类型更有限。YAML 更适合人工编辑的配置文件,JSON 更适合 API 和机器通信。YAML 是 JSON 的超集。
如何将 YAML 转换为 JSON?
可通过在线工具、命令行或编程库转换。CLI:安装 yq 执行 "yq -o=json file.yaml"。Python:使用 PyYAML 的 yaml.safe_load 加 json.dumps。JavaScript:使用 js-yaml 加 JSON.stringify。所有方法都是先解析 YAML 为原生数据结构,再序列化为 JSON。
何时使用 YAML,何时使用 JSON?
用 YAML 处理人类频繁编辑的配置文件(Kubernetes、Docker Compose、CI/CD),因其语法清晰、支持注释。用 JSON 处理 API 响应、服务间数据交换和浏览器应用。许多项目同时使用两者:YAML 用于配置,JSON 用于 API 通信。
掌握 YAML 到 JSON 的转换和 YAML 语法对现代 DevOps 和软件开发至关重要。通过理解 YAML 解析器的工作原理、避免布尔值陷阱等常见坑点,并遵循引用和验证的最佳实践,你可以编写出每次都能干净转换为 JSON 的健壮 YAML 配置。