← 全部文章

JSON vs YAML:差別與適用場景

JSON 與 YAML 比較:語法、型別、註解,以及像 Norway problem 之類的坑。YAML 是 JSON 的超集 —— 何時選哪一個、如何互轉。

JSON 與 YAML 解決的是同一個問題 —— 把結構化資料表示成文字 —— 但它們做的取捨剛好相反。JSON 為機器無歧義的解析最佳化;YAML 為人類書寫最佳化。自 YAML 1.2 起,每一份合法的 JSON 文件也是合法的 YAML。本指南比較它們的語法、型別與特性,並說明何時該選哪一個。

簡短答案

程式之間交換的資料用 JSON —— API 回應、訊息 payload、任何由機器產生的東西。需要人手寫或編輯的檔案用 YAML —— CI pipeline、Kubernetes manifest、應用設定 —— 這些場景中註解與可讀性很重要。

並排語法對比

相同的資料用兩種格式各寫一次:

# YAML
service: api
replicas: 3
ports:
  - 8080
  - 8443
env:
  LOG_LEVEL: info
  DEBUG: false
// JSON
{
  "service": "api",
  "replicas": 3,
  "ports": [8080, 8443],
  "env": {
    "LOG_LEVEL": "info",
    "DEBUG": false
  }
}

YAML 用縮排取代大括號與中括號,省掉了大多數引號,且允許註解。JSON 較囉嗦,但沒有有意義的空白,這讓它在解析與生成時都更容易做到可靠。

YAML 是 JSON 的超集合

自 YAML 1.2(2009)起,YAML 是 JSON 的嚴格超集合 —— 任何合法 JSON 文件都是合法 YAML,因為 YAML 直接採用了 JSON 的「flow」語法。所以你把 JSON 貼到 YAML 檔案裡就能直接運作。背後的歷史見 YAML 1.2 與 JSON 相容性

# 這是合法 YAML —— 同時也是合法 JSON
{"service": "api", "replicas": 3}

特性比較

特性JSONYAML
註解有(#
尾隨逗號不允許不適用(block 風格沒有逗號)
多行字串只能用轉義 \n原生支援(|>
Anchor / 參考有(& / *
單檔多文件不支援支援(用 --- 分隔)
有意義的空白有(縮排有意義)
解析複雜度極簡複雜
最適合機器資料交換人手編輯設定

型別處理:YAML 的尖刺

YAML 急於推斷型別,會出現 JSON 用強制引號就能避開的意外:

# 「Norway problem」—— 在 YAML 1.1 解析器裡這些會變布林
countries:
  - NO   # → false (!)
  - SE
  - true # → 布林,而非字串 "true"

version: 1.20   # → 數字 1.2,末尾的零丟掉了
zip: 01234      # → 668(在某些解析器裡被當成八進位)

JSON 完全沒有這些歧義:"NO" 永遠是字串 NO"01234" 永遠是那個字串。當 YAML 值必須是字串時,就明確加引號。

TOML 與 JSON5 的位置

另外兩種常見的「對人友善」設定格式經常出現在同一話題裡:

  • TOML —— section/key 風格,專為人手編輯的應用設定設計(Cargo、Poetry、Hugo)。比 YAML 更嚴格、沒有有意義的縮排,原生型別化的值(datetime、整數、浮點、陣列、行內表)。資料大多是扁平表時最合適。
  • JSON5 —— 給開發者用的寬鬆 JSON:允許註解、尾隨逗號、不加引號的 key、單引號、多行字串。不是 標準 JSON 解析器會接受的;你得用 JSON5 程式庫(或處理「註解 + 尾隨逗號」子集的 JSONC 解析器,例如 tsconfig.json)。

粗略定位:機器間交換用 JSON;深度巢狀、人手編輯的設定用 YAML;扁平的應用 / 工具設定用 TOML;想要「帶註解的 JSON」做編輯器設定又不想接受 YAML 的空白規則時,用 JSON5/JSONC

什麼時候用哪一個

  • 用 JSON:REST/GraphQL API、訊息佇列、瀏覽器 localStoragepackage.json、任何由程式碼產生或消費的東西。
  • 用 YAML:GitHub Actions / GitLab CI、Kubernetes 與 Docker Compose、Ansible playbook、需要人手編輯且要加註解的應用設定。

一個常見的模式:為了可讀性用 YAML 撰寫設定,然後在 build 或載入時轉成 JSON,讓應用程式本身只解析 JSON。

在 JSON 與 YAML 之間轉換

# Python —— YAML 轉 JSON
import yaml, json
data = yaml.safe_load(open('config.yaml'))
print(json.dumps(data, indent=2))

# 用 yq 在命令列
yq -o=json '.' config.yaml      # YAML → JSON
yq -P '.' config.json           # JSON → YAML

或在 fixjson 的 YAML ⇄ JSON 轉換器 立刻於瀏覽器中轉換 —— 貼 YAML 拿到 JSON(或反過來),資料不會送到任何伺服器。

常見問題

YAML 比 JSON 好嗎?

沒有誰「比較好」—— 它們是為不同工作調校的。人手編輯的設定 YAML 較佳(註解、可讀性);機器間資料交換 JSON 較佳(簡單、快、解析無歧義)。

JSON 是合法 YAML 嗎?

是。自 YAML 1.2 起,YAML 是 JSON 的嚴格超集合,所以任何合法 JSON 文件都是合法 YAML。反之不成立 —— 大多數 YAML 不是合法 JSON。

為什麼 YAML 把「NO」變成 false?

YAML 會從未加引號的 scalar 推斷型別,有些解析器會把 NOyesonoff 讀成布林值(「Norway problem」)。給值加引號("NO")就能強制當字串。JSON 用強制引號完全避開這個問題。

設定檔該用 YAML 還是 JSON?

需要人手編輯、需要註解與多行字串就用 YAML;由工具產生或消費就用 JSON。很多團隊用 YAML 撰寫,並於載入時轉成 JSON。

在瀏覽器裡轉換與驗證