YAML 转 JSON:在线转换与 JavaScript、Python、CLI 工具指南
在线及编程方式将 YAML 转换为 JSON。JavaScript、Python、Go 和命令行 YAML 转 JSON 完整指南。
YAML 是人类可读的配置格式,JSON 是 API 的通用语言。在线转换用 DevToolBox 的免费工具;代码中用 js-yaml(JavaScript)、PyYAML(Python)或 gopkg.in/yaml.v3(Go);命令行用 yq。注意 YAML 的布尔陷阱(yes/no/on/off)、制表符禁止、锚点展开等常见坑。多文档 YAML(---分隔)转换为 JSON 数组。
YAML 与 JSON — 核心区别
YAML(YAML Ain't Markup Language)和 JSON(JavaScript Object Notation)都是数据序列化格式,但设计哲学截然不同。YAML 面向人类编辑,以缩进表示层次;JSON 面向机器解析,语法严格无歧义。下表对比两者在实际使用中的关键差异:
| 特性 | YAML | JSON |
|---|---|---|
| 可读性 | 极佳,缩进语法,无多余标点 | 中等,大量引号和括号 |
| 注释支持 | 支持(# 开头) | 不支持 |
| 数据类型 | 字符串、整数、浮点数、布尔、null、日期、二进制 | 字符串、数字、布尔、null、数组、对象 |
| 文件大小 | 通常更小(无引号和括号) | 稍大(需引号和括号) |
| 解析速度 | 较慢(缩进敏感解析) | 较快(语法简单) |
| 典型用途 | Kubernetes、Docker Compose、CI/CD、Ansible | REST API、数据库、程序间通信 |
在线转换
最快的 YAML 转 JSON 方式是使用在线工具。DevToolBox 的 YAML to JSON 转换器支持实时预览、错误高亮和格式化输出——无需安装任何依赖。适合临时转换、调试配置文件或验证 YAML 语法。
对于需要集成到工程中的场景,请继续阅读以下各语言的代码示例和命令行方法。
JavaScript / Node.js — 使用 js-yaml
js-yaml 是 JavaScript 生态中最流行的 YAML 解析库,兼容 Node.js 和浏览器环境。核心 API 是 yaml.load()(解析 YAML → JS 对象)和 JSON.stringify()(序列化为 JSON)。
安装:
npm install js-yaml
# TypeScript types are bundled — no @types needed基本用法:
const yaml = require('js-yaml');
const yamlString = `
name: my-app
version: 1.0.0
database:
host: localhost
port: 5432
credentials:
user: admin
password: secret
features:
- auth
- logging
- metrics
enabled: true
`;
// Parse YAML → JavaScript object
const obj = yaml.load(yamlString);
// Serialize to JSON (pretty-printed with 2-space indent)
const json = JSON.stringify(obj, null, 2);
console.log(json);
/* Output:
{
"name": "my-app",
"version": "1.0.0",
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"user": "admin",
"password": "secret"
}
},
"features": ["auth", "logging", "metrics"],
"enabled": true
}
*/从文件读取并转换:
const yaml = require('js-yaml');
const fs = require('fs');
const path = require('path');
function yamlFileToJson(inputPath, outputPath) {
// Read YAML file
const yamlContent = fs.readFileSync(inputPath, 'utf8');
// Parse and convert
const obj = yaml.load(yamlContent);
const jsonContent = JSON.stringify(obj, null, 2);
// Write JSON file
if (outputPath) {
fs.writeFileSync(outputPath, jsonContent, 'utf8');
console.log(`Converted ${inputPath} → ${outputPath}`);
}
return jsonContent;
}
// Usage
yamlFileToJson('config.yaml', 'config.json');
yamlFileToJson('k8s-deployment.yaml', 'k8s-deployment.json');处理多文档 YAML(--- 分隔符):
const yaml = require('js-yaml');
const multiDocYaml = `
---
kind: Deployment
metadata:
name: api-server
---
kind: Service
metadata:
name: api-service
---
kind: ConfigMap
metadata:
name: api-config
`;
// yaml.load() only parses the FIRST document
// Use yaml.loadAll() for multi-document YAML
const documents = yaml.loadAll(multiDocYaml);
console.log(`Found ${documents.length} documents`);
// Convert the document array to JSON
const json = JSON.stringify(documents, null, 2);
console.log(json);
// Or process each document individually
documents.forEach((doc, index) => {
console.log(`Document ${index + 1}: ${doc.kind}`);
});Python — 使用 PyYAML
PyYAML 是 Python 的标准 YAML 库。始终使用 yaml.safe_load() 而非 yaml.load(),以防止来自不可信 YAML 的任意代码执行。
安装:
pip install pyyaml基本转换:
import yaml
import json
yaml_string = """
server:
host: 0.0.0.0
port: 8080
timeout: 30
database:
url: postgres://localhost/mydb
pool_size: 10
ssl: true
logging:
level: info
format: json
tags:
- production
- api
- v2
"""
# Parse YAML safely (prevents code execution from untrusted YAML)
data = yaml.safe_load(yaml_string)
# Serialize to JSON with indentation
json_output = json.dumps(data, indent=2)
print(json_output)
# Output:
# {
# "server": { "host": "0.0.0.0", "port": 8080, "timeout": 30 },
# "database": { "url": "postgres://localhost/mydb", "pool_size": 10, "ssl": true },
# "logging": { "level": "info", "format": "json" },
# "tags": ["production", "api", "v2"]
# }转换文件:
import yaml
import json
import sys
from pathlib import Path
def yaml_to_json(input_path: str, output_path: str = None) -> str:
"""Convert a YAML file to JSON."""
with open(input_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
json_str = json.dumps(data, indent=2, ensure_ascii=False)
if output_path:
with open(output_path, 'w', encoding='utf-8') as f:
f.write(json_str)
print(f"Converted {input_path} → {output_path}")
return json_str
# Convert a single file
result = yaml_to_json("config.yaml", "config.json")
# Convert multiple files in a directory
for yaml_file in Path(".").glob("**/*.yaml"):
json_file = yaml_file.with_suffix(".json")
yaml_to_json(str(yaml_file), str(json_file))多文档 YAML(yaml.safe_load_all):
import yaml
import json
multi_doc_yaml = """
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api
spec:
replicas: 3
---
apiVersion: v1
kind: Service
metadata:
name: web-api-svc
spec:
type: ClusterIP
port: 80
"""
# yaml.safe_load() only reads the first document
# yaml.safe_load_all() returns a generator for all documents
documents = list(yaml.safe_load_all(multi_doc_yaml))
print(f"Found {len(documents)} documents")
# Serialize the entire array to JSON
print(json.dumps(documents, indent=2))命令行工具
命令行转换适合 Shell 脚本、CI/CD 管道和快速一次性操作。以下是最常用的几种方式:
yq (推荐):
# Install yq (macOS)
brew install yq
# Install yq (Linux)
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
sudo chmod +x /usr/local/bin/yq
# Convert YAML file to JSON
yq -o json config.yaml
# Convert and save to file
yq -o json config.yaml > config.json
# Pretty-print with indentation
yq -o json -P config.yaml
# Convert from stdin
cat config.yaml | yq -o json
# Process specific keys during conversion
yq -o json '.database' config.yaml
# Convert multiple files
for f in *.yaml; do yq -o json "$f" > "${f%.yaml}.json"; donePython 一行命令(无需额外安装):
# Convert YAML stdin to JSON stdout
cat file.yaml | python3 -c "import yaml,json,sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))"
# Convert YAML file to JSON file
python3 -c "
import yaml, json
with open('input.yaml') as f:
data = yaml.safe_load(f)
with open('output.json', 'w') as f:
json.dump(data, f, indent=2)
"
# One-liner with file args
python3 -c "import yaml,json,sys; json.dump(yaml.safe_load(open(sys.argv[1])), open(sys.argv[2],'w'), indent=2)" input.yaml output.jsonRuby 一行命令:
# Ruby one-liner (available on most Unix systems)
ruby -ryaml -rjson -e 'puts JSON.pretty_generate(YAML.safe_load(STDIN.read))' < file.yamlYAML 数据类型映射到 JSON
了解 YAML 类型如何映射到 JSON 是避免转换错误的关键。以下表格展示了常见的类型映射:
| YAML 值 | JSON 输出 | 说明 |
|---|---|---|
| null, ~, (empty) | null | YAML 空值 |
| true, false | true, false | YAML 1.1/1.2 布尔值 |
| yes, no, on, off | true, false | 仅 YAML 1.1 视为布尔 |
| 42, -7 | 42, -7 | 整数 |
| 3.14, 1.0e10 | 3.14, 1.0e10 | 浮点数 |
| 0777 (octal) | 511 | 八进制 → 十进制整数 |
| 0xFF (hex) | 255 | 十六进制 → 十进制整数 |
| "hello", 'world' | "hello", "world" | 字符串(引号可选) |
| !!binary <base64> | "<base64>" | 二进制数据 → base64 字符串 |
| &anchor, *alias | 展开的值 | 锚点/别名完全展开 |
| - item1 - item2 | ["item1", "item2"] | 序列 → JSON 数组 |
| key: value | {"key": "value"} | 映射 → JSON 对象 |
YAML 锚点与别名
YAML 锚点(&)允许定义可复用的数据块,别名(*)引用它们。转换为 JSON 时,所有别名都会完全展开(内联替换),没有引用机制。合并键(<<: *base)也会展开,允许重复键以后者为准。
转换前(YAML):
# YAML with anchors and aliases
defaults: &defaults
timeout: 30
retries: 3
log_level: info
production:
<<: *defaults # Merge: inherits timeout, retries, log_level
log_level: warning # Override: replaces log_level from defaults
replicas: 5
staging:
<<: *defaults # Merge: inherits all defaults
replicas: 1
# Simple alias (not merge key)
base_image: &img "node:20-alpine"
services:
web:
image: *img # Alias: becomes "node:20-alpine"
worker:
image: *img # Alias: also becomes "node:20-alpine"转换后(JSON)— 锚点完全展开:
{
"defaults": { "timeout": 30, "retries": 3, "log_level": "info" },
"production": {
"timeout": 30,
"retries": 3,
"log_level": "warning",
"replicas": 5
},
"staging": {
"timeout": 30,
"retries": 3,
"log_level": "info",
"replicas": 1
},
"base_image": "node:20-alpine",
"services": {
"web": { "image": "node:20-alpine" },
"worker": { "image": "node:20-alpine" }
}
}注意:JSON 文件比 YAML 大,因为每个别名引用的值都被完全复制。在有大量锚点复用的场景下,这可能显著增加 JSON 体积。
多文档 YAML
YAML 支持在单个文件中包含多个文档,用 --- 分隔。这在 Kubernetes 中极为常见(一个 YAML 文件包含 Deployment + Service)。转换为 JSON 时,多文档变成 JSON 数组。
# Multi-document YAML (common in Kubernetes)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 8080JavaScript — yaml.loadAll():
const yaml = require('js-yaml');
const fs = require('fs');
const content = fs.readFileSync('k8s-manifests.yaml', 'utf8');
// yaml.load() → only parses FIRST document (wrong for multi-doc)
// yaml.loadAll() → parses ALL documents into an array
const documents = yaml.loadAll(content);
console.log(JSON.stringify(documents, null, 2));
// Result: [{ apiVersion: "apps/v1", kind: "Deployment", ... }, { apiVersion: "v1", kind: "Service", ... }]yq 命令行:
# yq automatically handles multi-document YAML
# Outputs as JSON array
yq -o json k8s-manifests.yaml
# Split into individual JSON files
yq -o json '.' k8s-manifests.yaml | jq -c '.[]' | while read doc; do
kind=$(echo "$doc" | jq -r '.kind')
echo "$doc" | jq . > "${kind,,}.json"
doneGo — gopkg.in/yaml.v3 + encoding/json
Go 使用 gopkg.in/yaml.v3 解析 YAML,encoding/json(标准库)序列化 JSON。强类型使转换显式可控。可用 interface{} 动态处理,也可定义结构体以获得类型安全。
// go get gopkg.in/yaml.v3
package main
import (
"encoding/json"
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// Dynamic approach — works for any YAML structure
func yamlToJsonDynamic(yamlBytes []byte) ([]byte, error) {
// Step 1: Parse YAML into generic interface{}
var obj interface{}
if err := yaml.Unmarshal(yamlBytes, &obj); err != nil {
return nil, fmt.Errorf("yaml parse error: %w", err)
}
// Step 2: Serialize to JSON
jsonBytes, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return nil, fmt.Errorf("json marshal error: %w", err)
}
return jsonBytes, nil
}
// Struct-based approach — type-safe, best for known schemas
type Config struct {
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Server struct {
Host string `yaml:"host" json:"host"`
Port int `yaml:"port" json:"port"`
} `yaml:"server" json:"server"`
Features []string `yaml:"features" json:"features"`
}
func main() {
yamlContent := []byte(`
name: my-service
version: "2.1.0"
server:
host: 0.0.0.0
port: 8080
features:
- auth
- rate-limiting
- tracing
`)
// Dynamic approach
jsonBytes, err := yamlToJsonDynamic(yamlContent)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fmt.Println(string(jsonBytes))
// Struct-based approach
var cfg Config
if err := yaml.Unmarshal(yamlContent, &cfg); err != nil {
panic(err)
}
out, _ := json.MarshalIndent(cfg, "", " ")
fmt.Println(string(out))
}Kubernetes 和 CI/CD 使用场景
将 YAML 转换为 JSON 在 DevOps 工作流中有多种实际应用:
1. 通过 Kubernetes API 操作资源:
# kubectl can apply both YAML and JSON
# Convert k8s manifest YAML to JSON for API calls
yq -o json deployment.yaml > deployment.json
# Use with curl to call the Kubernetes API directly
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
https://$K8S_API/apis/apps/v1/namespaces/default/deployments \
-d @deployment.json
# Validate manifest before applying
kubectl apply --dry-run=client -f deployment.yaml
yq -o json deployment.yaml | kubectl apply --dry-run=client -f -2. GitHub Actions 工作流转换:
# GitHub Actions step to convert YAML config to JSON for downstream tools
- name: Convert YAML config to JSON
run: |
pip install pyyaml
python3 -c "
import yaml, json
with open('config.yaml') as f:
data = yaml.safe_load(f)
with open('config.json', 'w') as f:
json.dump(data, f, indent=2)
"
echo "Config converted:"
cat config.json
# Or using yq in GitHub Actions
- name: Convert with yq
uses: mikefarah/yq@master
with:
cmd: yq -o json config.yaml > config.json3. Helm values.yaml 转 JSON(用于 Terraform):
# Convert Helm values.yaml to JSON for use in Terraform helm_release
yq -o json values.yaml > values.json
# In Terraform:
# resource "helm_release" "app" {
# values = [file("values.json")]
# }
# Or generate Terraform variables from YAML config
python3 -c "
import yaml, json
with open('app-config.yaml') as f:
config = yaml.safe_load(f)
# Write as Terraform tfvars JSON
with open('terraform.tfvars.json', 'w') as f:
json.dump(config, f, indent=2)
"常见陷阱与注意事项
1. 布尔陷阱(YAML 1.1)
YAML 1.1 将大量值视为布尔值。这是最常见的转换错误来源:
# YAML 1.1 boolean trap — these all become true or false in JSON!
country: NO # → false (Norway country code!)
debug: yes # → true
feature_flag: on # → true
cache: off # → false
verbose: y # → true (short form)
quiet: n # → false (short form)
# Fix: always quote ambiguous strings
country: "NO" # → "NO" (string)
debug: "yes" # → "yes" (string)
feature_flag: "on" # → "on" (string)
# YAML 1.2 only treats these as booleans:
# true, false (case-insensitive)
# All other values are strings2. 八进制数字(0777 → 511)
# File permissions as octal numbers become decimal integers!
chmod_value: 0777 # → 511 in JSON (not "0777"!)
umask: 022 # → 22 in JSON
# Fix: quote the value to keep it as a string
chmod_value: "0777" # → "0777" (string)
umask: "022" # → "022" (string)
# Or use explicit YAML tag
chmod_value: !!str 0777 # → "0777"3. 多行字符串(| 字面量 vs > 折叠)
# Literal block (|) — preserves newlines exactly
script: |
#!/bin/bash
echo "Starting..."
npm install
npm test
# JSON: "#!/bin/bash
echo "Starting..."
npm install
npm test
"
# Folded block (>) — joins lines with spaces (like HTML)
description: >
This is a long
description that
wraps across lines.
# JSON: "This is a long description that wraps across lines.
"
# Chomping indicators control trailing newlines:
# | (default) → keeps exactly one trailing newline
# |- → strips all trailing newlines
# |+ → keeps all trailing newlines4. 制表符禁止使用
# WRONG: tabs cause parse errors
server:
host: localhost # ← tab character → YAML parse error!
port: 8080
# CORRECT: always use spaces (2 is the convention)
server:
host: localhost # ← 2 spaces
port: 8080
# Configure your editor to insert spaces (not tabs) for .yaml files
# .editorconfig:
# [*.{yaml,yml}]
# indent_style = space
# indent_size = 2反向转换:JSON 转 YAML
将 JSON 转换为 YAML 同样简单。每个主流 YAML 库都支持此方向。注意:JSON 转 YAML 再转回 JSON 时,注释和格式会丢失。
JavaScript (js-yaml):
const yaml = require('js-yaml');
const jsonObj = {
name: "my-app",
version: "1.0.0",
server: { host: "0.0.0.0", port: 8080 },
features: ["auth", "logging"]
};
// yaml.dump() converts JS object → YAML string
const yamlOutput = yaml.dump(jsonObj, {
indent: 2, // 2-space indentation
lineWidth: 120, // wrap at 120 chars
noRefs: true, // don't use aliases in output
});
console.log(yamlOutput);
// name: my-app
// version: 1.0.0
// server:
// host: 0.0.0.0
// port: 8080
// features:
// - auth
// - loggingPython (PyYAML):
import yaml
import json
json_string = '{"name":"my-app","server":{"host":"localhost","port":8080},"tags":["api","v2"]}'
data = json.loads(json_string)
# yaml.dump() serializes Python dict → YAML string
yaml_output = yaml.dump(data, default_flow_style=False, indent=2, allow_unicode=True)
print(yaml_output)
# name: my-app
# server:
# host: localhost
# port: 8080
# tags:
# - api
# - v2yq 反向转换:
# Convert JSON to YAML with yq
yq -oy config.json # -o yaml (can also use --output-format=yaml)
yq -oy config.json > config.yaml
# Convert JSON stdin to YAML
echo '{"name":"app","port":3000}' | yq -oy- YAML 用于人类编辑的配置文件(Kubernetes、Docker Compose、GitHub Actions);JSON 用于 API 和机器间通信。
- 在线转换用 DevToolBox 的免费工具;代码中用 js-yaml (JS)、PyYAML (Python)、gopkg.in/yaml.v3 (Go);命令行用 yq。
- Python 中始终使用 yaml.safe_load() — yaml.load() 对不可信输入存在任意代码执行风险。
- 布尔陷阱:YAML 1.1 中 yes/no/on/off/y/n 都是布尔值。总是引用可能被误读的字符串。
- YAML 锚点(&)和别名(*)在 JSON 转换时完全展开,JSON 输出可能比 YAML 源文件大。
- 多文档 YAML(--- 分隔)用 yaml.loadAll() 或 yaml.safe_load_all() 处理,转换为 JSON 数组。
- YAML 禁止使用制表符缩进——总是用空格(2个空格是惯例)。用 .editorconfig 在编辑器中强制执行。