YAML和JSON是现代软件开发中最常用的两种数据序列化格式。YAML以其可读性著称,而JSON则以其通用性和严格的语法闻名。本指南将深入讲解两种格式的差异、转换原理和最佳实践。

目录

核心要点

  • YAML是JSON的超集:所有有效的JSON都是有效的YAML
  • 可读性差异:YAML更易于人类阅读,JSON更易于机器解析
  • 注释支持:YAML支持注释,JSON不支持
  • 数据类型:两者支持相同的基本数据类型
  • 应用场景:YAML常用于配置文件,JSON常用于API数据交换

需要快速转换YAML和JSON?试试我们的免费在线工具:

YAML转JSON | JSON转YAML

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的超集:

  1. 解析YAML:将YAML文本解析为内存中的数据结构
  2. 处理特殊语法
    • 展开锚点和别名
    • 处理多行字符串
    • 转换YAML特有的数据类型
  3. 序列化为JSON:将数据结构转换为JSON字符串
  4. 移除注释:JSON不支持注释,转换时会丢失

JSON转YAML

JSON转YAML需要考虑格式化选项:

  1. 解析JSON:将JSON文本解析为数据结构
  2. 格式化选项
    • 缩进大小(通常2或4空格)
    • 是否使用内联格式
    • 字符串引号策略
  3. 序列化为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?试试我们的免费在线工具:

YAML转JSON | JSON转YAML