jsonyamlconfiguration

JSON vs YAML:何时使用哪种格式?

· Cosyslabs

JSON是API、数据交换和机器生成配置的正确选择。YAML更适合由人工编写的配置文件,在这些文件中注释、可读性和最少的标点符号非常重要。YAML是JSON的超集——每个有效的JSON文档都是有效的YAML,但YAML有一些重要的陷阱,在采用之前必须了解。

语法比较

// JSON
{
  "server": {
    "host": "localhost",
    "port": 8080,
    "tls": true
  },
  "database": {
    "url": "postgres://localhost/mydb",
    "pool": {
      "min": 2,
      "max": 10
    }
  },
  "features": ["auth", "api", "admin"]
}
# YAML — 相同的数据,更易读
server:
  host: localhost
  port: 8080
  tls: true

database:
  url: postgres://localhost/mydb
  pool:
    min: 2
    max: 10

features:
  - auth
  - api
  - admin

YAML省去了引号、花括号、方括号和逗号。它使用缩进(仅空格——不使用制表符)来表达结构。

YAML是JSON的超集

您可以直接在YAML文件中嵌入JSON,它是有效的:

# 这是有效的YAML
name: Alice
config: {"debug": true, "level": 3}

这意味着YAML解析器可以解析JSON,YAML到JSON的转换是无损的(除了YAML特有的功能如锚点和注释,JSON无法表示这些)。

JSON的优势

API响应

JSON是REST API的通用语言。每个HTTP客户端,从 curl 到浏览器 fetch,都原生处理JSON:

const response = await fetch("/api/users");
const data = await response.json(); // 内置JSON解析

YAML没有浏览器原生支持,需要额外的解析器依赖(js-yaml约15KB)。

严格的类型处理

JSON有明确的类型:字符串、数字、布尔值、null、数组、对象。YAML从值推断类型,这会导致臭名昭著的错误。

机器生成的数据

生成配置或数据的程序应该输出JSON。JSON是明确的,广泛支持,不依赖于空白字符。

JavaScript生态系统

package.jsontsconfig.jsoneslintrc.json——JavaScript工具生态标准化使用JSON。编辑器提供带有自动补全和错误检测的JSON Schema验证。

YAML的优势

人工编写的配置

# YAML允许注释 — JSON不允许
# 这条注释解释了为什么超时时间很高
server:
  timeout: 30000  # 毫秒 — 旧版客户端需要更多时间

# 多行字符串在YAML中很易读
message: |
  欢迎使用系统。
  您的账户已创建。
  请检查您的电子邮件进行验证。

Kubernetes、GitHub Actions、Docker Compose

云原生生态系统将YAML标准化用于清单和流水线:

# GitHub Actions工作流
name: CI
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

多行字符串

YAML使用块标量优雅地处理多行字符串:

# 字面量块标量 — 保留换行符
description: |
  第一行。
  第二行。
  第三行。

# 折叠块标量 — 换行符变为空格
summary: >
  这段长文本在
  解析时将被折叠
  成一行。

JSON需要转义的 \n

{
  "description": "第一行。\n第二行。\n第三行。"
}

YAML的陷阱(挪威问题及其他)

YAML的类型推断导致了真实的生产事故。

挪威问题

countries:
  - GB
  - DE
  - NO   # YAML 1.1将此解析为布尔值false!
  - SE

在YAML 1.1(许多旧版解析器使用)中,noNONo 被解析为 false。同样,yesYESYes 变为 true。YAML 1.2(2009年)移除了这一行为,但许多解析器仍然实现1.1。

修复:对可能被误解的值加引号:

countries:
  - "GB"
  - "DE"
  - "NO"   # 现在安全地是字符串
  - "SE"

八进制数字解析

file_permissions: 0777  # YAML 1.1:解析为八进制511,而非十进制777!
port: 0755              # 八进制493

在YAML 1.2中,前导零不表示八进制。在1.1中,表示。对精度重要的数值加引号。

缩进错误

YAML只使用空格——混合使用制表符和空格会导致解析器错误:

server:
  host: localhost
	port: 8080  # 这里有制表符 — YAML解析错误!

重复键

config:
  debug: true
  debug: false  # 哪个生效?未定义行为

不同的解析器对重复键的处理方式不同(后者胜出、前者胜出或报错)。

转换

// YAML转JSON(Node.js)
import yaml from "js-yaml";
import fs from "fs";

const yamlContent = fs.readFileSync("config.yaml", "utf8");
const parsed = yaml.load(yamlContent);
const json = JSON.stringify(parsed, null, 2);
import yaml, json

with open("config.yaml") as f:
    data = yaml.safe_load(f)  # 使用safe_load,不要用load!

print(json.dumps(data, indent=2))

在Python中始终使用 yaml.safe_load(),而不是 yaml.load()。不安全版本可以通过YAML反序列化执行任意Python代码——这是一个已知的RCE向量。

决策指南

场景选择
REST API响应JSON
gRPC / Protocol Buffers两者都不(二进制)
package.jsontsconfig.jsonJSON
Kubernetes清单YAML
GitHub Actions / CIYAML
Docker ComposeYAML
Ansible PlaybooksYAML
需要注释的配置YAML
机器生成的配置JSON
人工编写的配置YAML
包含大量字符串的数据YAML(无需引号)

立即试用

使用JSON格式化工具YAML格式化工具即时在JSON和YAML之间转换——两者都完全在您的浏览器中运行。

更多Cosyslabs工具

  • PDF Convert All — 转换、合并和压缩PDF。许多文档生成流水线使用JSON或YAML配置驱动PDF渲染。
  • Unit Convert All — 转换配置文件中常见的测量值(如毫秒超时、MB文件大小)。
  • Rough Estimator — 估算在大型代码库中将基于JSON的配置系统迁移到YAML(或反之)的工作量。
  • Cosyslabs — Dev Tools !、Routine Toolkit等产品背后的工作室。