DevToolBox免费
博客

JSON vs YAML vs TOML:你应该用哪种配置格式?

10 分钟阅读作者 DevToolBox

JSON、YAML 和 TOML 是软件开发中最流行的三种配置格式。每种格式都有各自的优势和取舍。本指南提供全面的对比分析,帮助你为项目选择合适的格式。

使用我们的免费工具在 JSON 和 YAML 之间即时转换 →

各格式概述

JSON(JavaScript 对象表示法)

JSON 由 Douglas Crockford 在 2000 年代初期提出,是一种源自 JavaScript 对象字面量语法的轻量级数据交换格式。其设计目标是简洁:用最少的规则使任何编程语言都能轻松解析。如今它是 Web API、配置文件(如 package.jsontsconfig.json)以及数据存储的事实标准

YAML(YAML Ain't Markup Language)

YAML 于 2001 年由 Clark Evans、Ingy döt Net 和 Oren Ben-Kiki 首次提出。最初名为"Yet Another Markup Language",后更名以体现其面向数据(而非文档)的本质。YAML 为人类可读性而设计,广泛用于 DevOps 工具,如 Docker Compose、Kubernetes 清单、Ansible Playbook 以及 CI/CD 配置(GitHub Actions、GitLab CI)。

TOML(Tom 的明显最小化语言)

TOML 由 Tom Preston-Werner(GitHub 联合创始人)于 2013 年创建,专门作为一种最小化且无歧义的配置格式。其目标是语义明显、易于阅读,能清晰地映射到哈希表。TOML 是 Rust(Cargo.toml)、Python(pyproject.toml)和 Hugo 静态网站的标准配置格式。

语法对比

下面用三种格式表达相同的配置:

JSON

{
  "server": {
    "host": "localhost",
    "port": 8080,
    "debug": true
  },
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "name": "myapp",
    "credentials": {
      "username": "admin",
      "password": "secret"
    }
  },
  "features": ["auth", "logging", "cache"],
  "max_connections": 100
}

YAML

# Server configuration
server:
  host: localhost
  port: 8080
  debug: true

# Database settings
database:
  host: db.example.com
  port: 5432
  name: myapp
  credentials:
    username: admin
    password: secret

features:
  - auth
  - logging
  - cache

max_connections: 100

TOML

# Server configuration
max_connections = 100
features = ["auth", "logging", "cache"]

[server]
host = "localhost"
port = 8080
debug = true

[database]
host = "db.example.com"
port = 5432
name = "myapp"

[database.credentials]
username = "admin"
password = "secret"

功能对比

特性JSONYAMLTOML
注释不支持支持(#)支持(#)
数据类型字符串、数字、布尔值、null、数组、对象字符串、整数、浮点数、布尔值、null、日期、数组、映射 + 自定义标签字符串、整数、浮点数、布尔值、日期时间、数组、表
可读性中等——大括号和引号增加视觉噪音高——基于缩进的简洁语法高——类 INI 格式,段落分明
严格性非常严格——不允许尾随逗号和注释宽松——隐式类型推断可能产生意外严格——显式类型,极少歧义
工具支持出色——所有语言都有原生解析器良好——所有主流语言都有解析器良好——在 Rust/Python/Go 中支持良好
多行字符串不支持(使用 \n 转义序列)支持(| 保留换行,> 折叠换行)支持(三引号字符串)

何时使用各格式

使用 JSON 的场景

  • 构建或使用 REST API——JSON 是通用的 API 载荷格式
  • 使用 package.jsontsconfig.jsoncomposer.json
  • 存储机器读取多于人类读取的数据(日志、导出)
  • 需要最广泛的工具和解析器支持
  • 不同编程语言之间的数据交换
// Typical JSON use cases
// package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build"
  }
}

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true
  }
}

使用 YAML 的场景

  • 编写 Docker Compose 文件或 Kubernetes 清单
  • 配置 CI/CD 流水线(GitHub ActionsGitLab CICircleCI
  • 使用 Ansible Playbook 或 Helm Charts
  • 需要在配置中添加注释
  • 人类可读性是首要考虑且能保持缩进规范
# Docker Compose
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html

# GitHub Actions
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

使用 TOML 的场景

  • 配置 Rust 项目(Cargo.toml
  • 配置 Python 项目(pyproject.tomlPoetryBlackRuff
  • 配置 Hugo 静态网站生成器
  • 需要无隐式类型转换的明确格式
  • 配置有清晰的分组结构(TOML 的表很适合这种情况)
# Cargo.toml (Rust)
[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

# pyproject.toml (Python)
[project]
name = "my-package"
version = "1.0.0"
requires-python = ">=3.9"

[tool.ruff]
line-length = 88
target-version = "py39"

常见陷阱

YAML:缩进问题

YAML 使用缩进定义结构。混用制表符和空格,或缩进层级不一致,是 YAML 最常见的错误来源。

# BAD: mixing tabs and spaces (invisible but breaks YAML)
services:
	web:          # tab character - YAML error!
    image: nginx

# BAD: inconsistent indentation
services:
  web:
      image: nginx   # 4 spaces here
    ports:            # 2 spaces here - error!
      - "80:80"

# GOOD: consistent 2-space indentation
services:
  web:
    image: nginx
    ports:
      - "80:80"

YAML:"挪威问题"

在 YAML 1.1 中,未加引号的 NOyesonoff 会被解释为布尔值。国家代码"NO"(挪威)会变成 false。这已导致了实际的 Bug。YAML 1.2 修复了这一问题,但很多解析器仍默认使用 1.1 的行为。

# The "Norway Problem" - YAML 1.1
countries:
  - name: Norway
    code: NO          # Parsed as boolean false!
  - name: Sweden
    code: SE          # Parsed as string "SE"
  - name: Finland
    code: FI          # Parsed as string "FI"

# Other surprising boolean values in YAML 1.1:
truthy:  yes          # boolean true
falsy:   no           # boolean false
enabled: on           # boolean true
disabled: off         # boolean false
positive: TRUE        # boolean true
negative: False       # boolean false

# FIX: Always quote values that could be misinterpreted
countries:
  - name: Norway
    code: "NO"        # Now correctly a string
  - name: Sweden
    code: "SE"
settings:
  enabled: "yes"      # Now correctly a string

JSON:尾随逗号

JSON 不允许尾随逗号。在数组或对象的最后一个元素后加逗号会导致解析错误。这是手动编辑 JSON 文件时最常见的错误之一。

// BAD: trailing comma after last element
{
  "name": "my-app",
  "version": "1.0.0",
  "private": true,    // <-- trailing comma = PARSE ERROR
}

// BAD: trailing comma in array
{
  "colors": [
    "red",
    "green",
    "blue",            // <-- trailing comma = PARSE ERROR
  ]
}

// GOOD: no trailing commas
{
  "name": "my-app",
  "version": "1.0.0",
  "private": true
}

TOML:嵌套表语法

TOML 中的深层嵌套结构可能变得冗长。每一层都需要自己的 [section.subsection] 头部,对于复杂层级关系来说不如 JSON 或 YAML 的嵌套直观。

# TOML: deeply nested config can be verbose
[server]
host = "localhost"

[server.ssl]
enabled = true

[server.ssl.certificates]
cert = "/path/to/cert.pem"
key = "/path/to/key.pem"

[server.ssl.certificates.ca]
bundle = "/path/to/ca-bundle.pem"

# The same in YAML is more compact:
# server:
#   host: localhost
#   ssl:
#     enabled: true
#     certificates:
#       cert: /path/to/cert.pem
#       key: /path/to/key.pem
#       ca:
#         bundle: /path/to/ca-bundle.pem

# TOML inline tables can help for shallow nesting:
[server]
host = "localhost"
ssl = { enabled = true, cert = "/path/to/cert.pem" }

转换工具

需要在格式之间切换?使用我们的免费在线转换器:

JSON ↔ YAML 转换器——支持双向转换和格式化选项

TOML ↔ YAML 转换器——在 TOML 和 YAML 之间即时转换

常见问题

JSON、YAML 和 TOML 哪个解析最快?

JSON 通常解析最快,因为其语法简单严格。大多数 JSON 解析器已高度优化且有原生实现。TOML 由于语法无歧义也很快。YAML 通常最慢,因为其规范复杂,包含锚点、自定义标签和隐式类型推断等特性。

JSON 能使用注释吗?

标准 JSON(RFC 8259)不支持注释。JSON5 和 JSONC(VS Code 设置使用的格式)等工具扩展了 JSON 以支持注释,但这些是非标准的。如果需要注释,可以考虑使用 YAML 或 TOML,或使用在解析前去除注释的 JSON 预处理器。

为什么 YAML 把 "NO" 当作 false?

在 YAML 1.1 中,yes/no、on/off 和 true/false 都被识别为布尔值(不区分大小写)。因此国家代码"NO"会被解释为布尔值 false。这被称为"挪威问题"。为避免此问题,对可能被误解的字符串值始终加引号:使用 "NO" 而不是 NO。YAML 1.2 将布尔值限制为仅 true/false,但许多解析器仍默认使用 YAML 1.1 规则。

TOML 比 YAML 更适合配置文件吗?

TOML 通常被认为更适合简单、扁平的配置文件,因为它没有隐式类型转换,比 YAML 更不容易出错。但 YAML 处理深层嵌套和复杂结构更优雅。在 Rust 和 Python 生态中,TOML 是标准选择;在 DevOps 和 Kubernetes 领域,YAML 仍占主导地位。

在 JSON、YAML 和 TOML 之间转换会丢失数据吗?

对于大多数常见数据结构(字符串、数字、布尔值、数组、对象),三种格式之间的转换是无损的。但某些特性是格式特有的:YAML 的锚点和自定义标签在 JSON 或 TOML 中没有等价物;TOML 的日期时间类型在 JSON 中可能丢失精度;JSON 不支持注释,因此从 YAML/TOML 转换到 JSON 会丢失所有注释。

使用我们的免费工具在 JSON 和 YAML 之间即时转换 →

使用我们的免费工具在 TOML 和 YAML 之间即时转换 →

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

Y{}JSON ↔ YAML ConverterTYTOML ↔ YAML{ }JSON FormatterYMLYAML Validator & Formatter

相关文章

Cron 表达式实例:每 5 分钟、每天、每周、每月

通过实用示例掌握 cron 表达式。学习如何设置每 5 分钟、每小时、每天、每周和每月的定时任务。

Docker Compose YAML 验证:10 个常见语法错误及修复方法

别再浪费时间在 Docker Compose YAML 错误上。学会识别和修复 10 个最常见的语法错误。