YAML和JSON是现代软件开发中最常用的两种数据序列化格式。YAML以其可读性著称,而JSON则以其通用性和严格的语法闻名。本指南将深入讲解两种格式的差异、转换原理和最佳实践。
目录
核心要点
- YAML是JSON的超集:所有有效的JSON都是有效的YAML
- 可读性差异:YAML更易于人类阅读,JSON更易于机器解析
- 注释支持:YAML支持注释,JSON不支持
- 数据类型:两者支持相同的基本数据类型
- 应用场景:YAML常用于配置文件,JSON常用于API数据交换
需要快速转换YAML和JSON?试试我们的免费在线工具:
YAML vs JSON 对比
| 特性 | YAML | JSON |
|---|---|---|
| 可读性 | 高(缩进结构) | 中(括号结构) |
| 注释 | 支持(#) | 不支持 |
| 数据类型 | 字符串、数字、布尔、null、数组、对象 | 相同 |
| 文件扩展名 | .yaml, .yml | .json |
| 引号要求 | 大多数情况可选 | 字符串必须用双引号 |
| 多文档 | 支持(---分隔) | 不支持 |
| 锚点和别名 | 支持 | 不支持 |
| 解析速度 | 较慢 | 较快 |
| 常见用途 | 配置文件、CI/CD | API、数据存储 |
YAML语法详解
基本结构
# 这是注释
name: John Doe
age: 30
active: true
email: null
# 嵌套对象
address:
city: Beijing
country: China
zipcode: "100000"
# 数组
hobbies:
- reading
- coding
- gaming
# 内联数组
skills: [JavaScript, Python, Go]
# 内联对象
metadata: {created: 2024-01-01, updated: 2024-06-01}
多行字符串
# 保留换行符(|)
description: |
This is a long description
that spans multiple lines.
Each line break is preserved.
# 折叠换行符(>)
summary: >
This is a long summary
that will be folded into
a single line.
# 带缩进的多行
code: |2
function hello() {
console.log("Hello");
}
锚点和别名
# 定义锚点
defaults: &defaults
adapter: postgres
host: localhost
port: 5432
# 使用别名
development:
<<: *defaults
database: dev_db
production:
<<: *defaults
database: prod_db
host: prod.example.com
数据类型
# 字符串
string1: Hello World
string2: "Hello World"
string3: 'Hello World'
# 数字
integer: 42
float: 3.14
scientific: 1.0e+12
hex: 0xFF
octal: 0o755
# 布尔值
bool1: true
bool2: false
bool3: yes
bool4: no
# 空值
null1: null
null2: ~
null3:
# 日期时间
date: 2024-01-15
datetime: 2024-01-15T10:30:00Z
JSON语法详解
基本结构
{
"name": "John Doe",
"age": 30,
"active": true,
"email": null,
"address": {
"city": "Beijing",
"country": "China",
"zipcode": "100000"
},
"hobbies": [
"reading",
"coding",
"gaming"
],
"skills": ["JavaScript", "Python", "Go"]
}
数据类型
{
"string": "Hello World",
"integer": 42,
"float": 3.14,
"scientific": 1.0e12,
"boolTrue": true,
"boolFalse": false,
"nullValue": null,
"array": [1, 2, 3],
"object": {"key": "value"}
}
转换原理
YAML转JSON
YAML转JSON的过程相对简单,因为YAML是JSON的超集:
- 解析YAML:将YAML文本解析为内存中的数据结构
- 处理特殊语法:
- 展开锚点和别名
- 处理多行字符串
- 转换YAML特有的数据类型
- 序列化为JSON:将数据结构转换为JSON字符串
- 移除注释:JSON不支持注释,转换时会丢失
JSON转YAML
JSON转YAML需要考虑格式化选项:
- 解析JSON:将JSON文本解析为数据结构
- 格式化选项:
- 缩进大小(通常2或4空格)
- 是否使用内联格式
- 字符串引号策略
- 序列化为YAML:按照YAML语法规则输出
代码示例
JavaScript/Node.js
// 使用 js-yaml 库
// npm install js-yaml
const yaml = require('js-yaml');
// YAML 转 JSON
const yamlString = `
name: John Doe
age: 30
hobbies:
- reading
- coding
`;
const jsonObject = yaml.load(yamlString);
const jsonString = JSON.stringify(jsonObject, null, 2);
console.log(jsonString);
// JSON 转 YAML
const jsonData = {
name: "Jane Doe",
age: 25,
skills: ["Python", "JavaScript"]
};
const yamlOutput = yaml.dump(jsonData, {
indent: 2,
lineWidth: 80,
noRefs: true
});
console.log(yamlOutput);
Python
import yaml
import json
# YAML 转 JSON
yaml_string = """
name: John Doe
age: 30
hobbies:
- reading
- coding
"""
data = yaml.safe_load(yaml_string)
json_string = json.dumps(data, indent=2, ensure_ascii=False)
print(json_string)
# JSON 转 YAML
json_data = {
"name": "Jane Doe",
"age": 25,
"skills": ["Python", "JavaScript"]
}
yaml_output = yaml.dump(json_data, allow_unicode=True, default_flow_style=False)
print(yaml_output)
Go
package main
import (
"encoding/json"
"fmt"
"gopkg.in/yaml.v3"
)
func main() {
// YAML 转 JSON
yamlData := []byte(`
name: John Doe
age: 30
hobbies:
- reading
- coding
`)
var data map[string]interface{}
yaml.Unmarshal(yamlData, &data)
jsonData, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(jsonData))
// JSON 转 YAML
jsonInput := map[string]interface{}{
"name": "Jane Doe",
"age": 25,
"skills": []string{"Go", "Python"},
}
yamlOutput, _ := yaml.Marshal(jsonInput)
fmt.Println(string(yamlOutput))
}
常见使用场景
1. Kubernetes配置
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:1.0.0
ports:
- containerPort: 8080
2. Docker Compose
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
depends_on:
- db
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
3. CI/CD配置(GitHub Actions)
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
4. API响应(JSON)
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
{
"id": 2,
"name": "Jane Doe",
"email": "jane@example.com"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 100
}
}
}
最佳实践
1. 选择合适的格式
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| 配置文件 | YAML | 可读性好,支持注释 |
| API数据 | JSON | 通用性强,解析快 |
| 数据存储 | JSON | 格式严格,易于验证 |
| CI/CD配置 | YAML | 行业标准 |
| 前端配置 | JSON | 原生支持 |
2. YAML编写规范
# 使用一致的缩进(推荐2空格)
server:
host: localhost
port: 8080
# 复杂字符串使用引号
message: "Hello: World"
path: "/api/v1/users"
# 使用注释说明配置项
database:
# 数据库连接池大小
pool_size: 10
# 连接超时时间(秒)
timeout: 30
3. JSON编写规范
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp",
"pool": {
"min": 5,
"max": 20
}
}
}
4. 转换注意事项
- 注释丢失:YAML转JSON会丢失注释
- 数据类型:注意YAML的隐式类型转换(如
yes变成true) - 特殊字符:包含特殊字符的字符串需要引号
- 精度问题:大数字可能有精度损失
常见问题
YAML中的字符串什么时候需要引号?
以下情况需要引号:
- 包含特殊字符(
:,#,{,},[,]等) - 以特殊字符开头
- 看起来像其他数据类型(如
yes,no,true,1.0) - 包含前导或尾随空格
如何在JSON中添加注释?
JSON标准不支持注释。替代方案:
- 使用YAML格式
- 使用JSON5(非标准扩展)
- 使用特殊键名如
"_comment"
YAML的锚点转换为JSON后会怎样?
锚点和别名会被展开,转换为完整的数据副本。
为什么YAML解析比JSON慢?
YAML语法更复杂,支持更多特性(锚点、多行字符串等),需要更多解析步骤。
总结
YAML和JSON各有优势,选择合适的格式取决于具体使用场景。理解两种格式的差异和转换原理,可以帮助你更高效地处理配置文件和数据交换。
快速总结:
- YAML适合配置文件,可读性好,支持注释
- JSON适合API数据交换,通用性强,解析快
- YAML是JSON的超集,转换相对简单
- 注意转换时的数据类型和注释丢失问题
需要快速转换YAML和JSON?试试我们的免费在线工具: