跳至內容
Toova
所有工具

JSON vs YAML — 何時使用何者

Toova

JSON 與 YAML 都是將結構化資料以文字表示的方式。兩者都支援字串、數字、布林、陣列與巢狀物件。兩者都在所有程式語言與平台上廣泛受支援。然而它們在權衡上截然不同:JSON 針對機器可讀性與解析速度最佳化;YAML 針對人類可讀性與表達豐富的設定最佳化。知道何時選用何者,可避免使用為 API 設計的設定格式撰寫手寫設定檔(或反之)所帶來的摩擦。

本指南涵蓋語法差異、各格式實際的優缺點、依格式而定的真實工具選擇、效能考量,以及 2026 年的明確決策架構。

JSON 概覽

JSON(JavaScript Object Notation)由 Douglas Crockford 於 2000 年代初期正式化,並在 RFC 8259 與 ECMA-404 中標準化。其設計目標是極簡、無歧義的格式,讓任何程式語言都能解析與序列化,而不需要複雜的解析器。

JSON 確切支援六種資料型別:字串(永遠使用雙引號)、數字、布林(true/false)、null、物件(具字串鍵的鍵值映射)與陣列(有序列表)。沒有註解、沒有日期型別、沒有二進位型別、沒有引用。這種極簡是刻意的:嚴格規則消除了歧義,並讓解析器簡單而快速。

{
  "name": "deploy-service",
  "version": "2.1.0",
  "environment": "production",
  "replicas": 3,
  "enabled": true,
  "tags": ["backend", "critical"],
  "resources": {
    "cpu": "500m",
    "memory": "512Mi"
  }
}

每個鍵都必須用雙引號包住。不允許尾隨逗號。沒有撰寫註解的方式。除非跳脫換行字元,否則字串不能跨多行。這些限制讓 JSON 較難手寫,但易於從程式碼產生並在接收端解析。

YAML 概覽

YAML(YAML Ain't Markup Language)由 Clark Evans、Ingy dot Net 與 Oren Ben-Kiki 自 2001 年起設計。版本 1.2 達到與 JSON 相容,於 2009 年定稿。YAML 的設計目標是人類可讀的資料格式,讓開發者能在文字編輯器中直接撰寫,而不必學習新語法。完整規格位於 yaml.org

YAML 使用縮排來表達結構,而非括號。列表使用連字號。鍵預設不加引號。註解以 # 開頭。除非字串包含特殊字元,否則不需引號。多行字串有專用的區塊純值語法。

# 生產環境部署設定
name: deploy-service
version: 2.1.0
environment: production
replicas: 3
enabled: true

tags:
  - backend
  - critical

resources:
  cpu: 500m
  memory: 512Mi

相同資料結構以 YAML 表達顯著較短且較易讀 — 特別是當它包含註解或巢狀列表時。代價是 YAML 的解析器必須處理顯著更高的複雜度:縮排敏感性、表達相同型別的多種方式、錨點、別名、合併鍵,以及歷史遺留的布林解讀歧義。

並排語法比較

多行字串

多行字串是 YAML 在設定檔上最明顯的優勢之一。YAML 提供兩種區塊純值樣式:字面(|)會完整保留換行,折疊(>)會以空格合併行,適合長段落。

# YAML:撰寫多行字串的多種方式
# 字面區塊(保留換行)
description: |
  This is line one.
  This is line two.
  Final line with trailing newline.

# 折疊區塊(換行變為空格,適合長段落)
summary: >
  This long paragraph is written across
  multiple lines but will be joined into
  a single space-separated string.

# 在 JSON 中,你必須跳脫換行
# "description": "This is line one.
This is line two.
Final line."

錨點與別名

YAML 錨點(&)與別名(*)讓你能定義一次值,並在多處引用,類似變數。合併鍵(<<)將映射的內容合併到另一個映射中,提供一種繼承形式。

# YAML 錨點與別名能減少重複
defaults: &defaults
  timeout: 30
  retries: 3
  log_level: info

development:
  <<: *defaults   # 合併預設
  log_level: debug

staging:
  <<: *defaults
  timeout: 60

production:
  <<: *defaults

JSON 沒有對應功能。在 JSON 中,重複的設定必須複製、由範本層處理,或由使用的應用程式邏輯管理。YAML 錨點對人類維護的設定很強大,但對不熟悉此慣例的讀者來說,會讓檔案較難理解。

優缺點

JSON 優點

  • 無歧義解析 — 語法簡單到可以用一頁說明。每個解析器對給定輸入都產出相同結果。
  • 速度 — JSON 解析器是現存最快的文字解析器之一。V8 解析 JSON 比執行 JavaScript 本身還快。
  • 原生 JavaScript 支援JSON.parse()JSON.stringify() 內建於每個 JavaScript 執行環境。無需相依套件。
  • 通用工具 — 每個 API 客戶端、資料庫與資料管線都原生支援 JSON。它是事實上的 API 格式。
  • 不對縮排敏感 — 空白與語意無關,使 JSON 對編輯器、作業系統與工具之間的格式化差異具堅固性。

JSON 缺點

  • 無註解 — 你無法行內解釋設定值。這對手寫檔案是顯著痛點。
  • 對人類冗長 — 所有鍵都必須加引號,每個項目以逗號分隔,每個物件與陣列都被括號包圍。
  • 尾隨逗號錯誤 — 在最後一個陣列或物件元素後的尾隨逗號為無效,造成手動編輯時容易出現的解析錯誤。
  • 無多行字串 — 表示含嵌入換行的字串需要 \n 跳脫,使嵌入 SQL 查詢或 shell 腳本變得痛苦。
  • 無日期型別 — 日期是字串。慣例不一(ISO 8601、Unix 時間戳、自訂格式)且必須由應用程式處理。

YAML 優點

  • 註解# 註解語法讓 YAML 成為需要行內文件之設定檔的明顯選擇。
  • 可讀性 — 較少語法噪音。不加引號的鍵、無逗號、基於縮排的結構,與人類撰寫大綱的方式相符。
  • 多行字串 — 字面與折疊區塊純值能優雅處理長字串,無需跳脫。
  • 錨點與合併鍵 — 在大型設定檔中減少重複。
  • 豐富的型別系統 — YAML 解析器會從值的格式推斷型別(字串、整數、浮點數、布林、null、時間戳),無需明確型別註記。

YAML 缺點

  • 複雜度 — 完整的 YAML 規格非常龐大。邊界情況繁多:挪威問題、隱式型別強制轉換的意外、tab 與 space 的敏感性。
  • 解析較慢 — 由於語法複雜,YAML 解析器比 JSON 解析器明顯較慢。
  • 縮排錯誤 — 單一不對齊的行就會改變文件的意義,而不會產生解析錯誤,造成難以發現的細微錯誤。
  • 挪威問題 — 在 YAML 1.1 中,裸寫的 NO 會被解析為布林 false。國碼、縮寫與許多英文單字在 YAML 1.1 解析器中(仍常見)有意外的布林解讀。
  • 解析器行為不一致 — 不同語言的 YAML 解析器實作規格的不同子集或不同版本,導致可移植性問題。

何時使用 JSON

API 回應與請求

JSON 是 REST API 的通用格式。每個 HTTP 客戶端函式庫都能原生序列化與反序列化它。在 API 規模下,解析速度很重要,而 JSON 無歧義的語法代表每個客戶端與伺服器都會以相同方式解析相同資料。GraphQL 回應是 JSON。OpenAPI/Swagger 定義是 JSON(不過 YAML 也被接受)。如果你在設計 API,預設使用 JSON。

{
  "user": {
    "id": 42,
    "email": "alice@example.com",
    "roles": ["admin", "editor"],
    "createdAt": "2026-01-15T10:30:00Z"
  }
}

由程式碼產生的設定

當程式產生設定時 — 建構工具輸出相依套件鎖定檔、框架產生專案清單、部署工具記錄 checksum — JSON 是正確的格式。輸出永遠不需要手寫、不需要註解,JSON 無歧義的語法確保使用程式碼正確解析所產生的內容。package.jsontsconfig.jsonpackage-lock.jsoncomposer.json 都是此模式的範例。

服務間的資料交換

當兩個服務需要交換資料時 — 訊息佇列、webhook、事件串流 — JSON 的速度、通用性與無歧義使其成為正確選擇。在自動化資料管線中,YAML 的優點(註解、多行字串)並不重要。使用 JSON 格式化工具在除錯時檢查載荷,並使用 JSON 轉 YAML 轉換器,在需要為了文件用途讓載荷變得人類可讀時使用。

儲存於資料庫中

PostgreSQL、MongoDB、MySQL 以及多數儲存結構化資料的資料庫,都以 JSON 或 JSON 相容格式儲存。YAML 不是任何主要資料庫支援的儲存格式。如果你在資料庫中儲存設定或結構化資料,請使用 JSON。

何時使用 YAML

基礎設施與部署設定

Kubernetes 清單、Helm chart、Docker Compose 檔案與 Ansible playbook 都使用 YAML。這些檔案由人類撰寫與審查,經常包含解釋性註解,並從 YAML 用於描述資源集合的可讀列表語法中獲益。具多個容器、卷掛載與環境變數的 Kubernetes Deployment 在 YAML 中明顯比 JSON 易讀。

CI/CD 管線定義

GitHub Actions、GitLab CI、CircleCI 與 Bitbucket Pipelines 全都使用 YAML 作為管線定義。管線設定由人類撰寫、經常加註解,並包含從 YAML 可讀語法中獲益的多步驟邏輯。

# GitHub Actions 工作流程 — YAML 是自然之選
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

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

應用程式設定檔

Django 設定(透過 django-configurations)、Ruby on Rails 的 database.yml、Gatsby 設定與許多其他框架都使用 YAML 作為設定。當開發者需要將設定檔與程式碼一起閱讀並理解時,YAML 能包含註解與多行解釋的能力,減少了認知負擔。

文件資料

Jekyll、Hugo 與 Eleventy 等靜態網站產生器在內容檔案中使用 YAML 前言。YAML 中繼資料與 Markdown 主體內容的組合很普及,因為 YAML 的可讀鍵值語法自然契合文字文件頂部。JSON 前言存在但很少被偏好使用。

效能

對於資料處理管線,序列化基準測試一致顯示在等效資料上 JSON 比 YAML 解析快 5-10 倍。V8 的 JSON.parse() 呼叫處理 1 MB 檔案只需數毫秒。同等的 YAML 解析則需數十毫秒。對於每秒處理數千個請求的網頁伺服器,此差異很重要。對於啟動時讀取一次設定檔的 CLI 工具則不重要。

如果效能是主要考量,而你正在為高吞吐量資料格式在 JSON 與 YAML 間選擇,JSON 毫無疑問勝出。如果你需要更快的解析,可考慮 MessagePack 或 Protocol Buffers 等二進位格式用於服務間通訊。

資安考量

YAML 解析器比 JSON 解析器複雜且攻擊面更大。最顯著的風險是透過 YAML 反序列化進行任意程式碼執行。在 Python 的 PyYAML 中(在 safe_load 預設執行前),使用預設的 yaml.load() 函數載入不信任的 YAML,可能會執行嵌入在 YAML 中的任意 Python 程式碼。PHP 與 Ruby 的 YAML 解析器也曾有類似漏洞。

規則:在解析不信任的 YAML 時,請務必使用安全載入。在 Python 中使用 yaml.safe_load(),切勿使用無 Loader 參數的 yaml.load()。在 Java 中,設定建構子以限制允許的型別。在 Ruby 中使用 YAML.safe_load(),而非 YAML.load()

JSON 解析器沒有此漏洞,因為 JSON 的型別系統沒有可執行值的概念。JSON 解析器只能產出字串、數字、布林、null、陣列與物件 — 絕不會是程式碼。處理不信任的使用者資料時,JSON 在解析上本質上更安全。

JSON 與 YAML 之間的轉換

兩種格式在最常見的資料型別上語意相容。當資料不使用 YAML 特有功能(錨點、自訂型別、區塊純值)時,兩者間轉換很直接。使用 JSON 轉 YAML 轉換器將 API 回應或鎖定檔轉為可讀的 YAML,用於文件或除錯。使用 YAML 轉 JSON 轉換器將 YAML 設定餵入 JSON 原生工具或 API。兩個工具都在瀏覽器中執行 — 你的資料絕不離開裝置。

JSON 格式化工具對於在轉換前檢查與驗證 JSON 結構很有用。如果你處理的設定經常在格式間移動 — 例如需要序列化以進行 API 呼叫的 Kubernetes 清單 — 將兩個轉換器都收藏起來能節省時間。

決策架構

  • 撰寫 REST API 回應或請求?JSON。
  • 設定 Kubernetes、Docker Compose 或 Ansible?YAML。
  • 撰寫 CI/CD 管線?YAML。
  • 將資料儲存在資料庫中?JSON。
  • 撰寫人類可編輯且帶註解的設定檔?YAML。
  • 從程式碼以程式化方式產生設定?JSON。
  • 處理不信任的使用者輸入?JSON(更安全的解析器)。
  • 高吞吐量資料管線?JSON(或二進位格式)。
  • 專案已一致使用某種格式?遵循現有慣例。

當有疑慮時,最重要的因素是會閱讀與撰寫該檔案的人類。如果檔案主要由機器產生並由機器使用,JSON 的簡潔性勝出。如果人類會閱讀、編輯它,並在意其清晰度,YAML 的表達能力值得額外的解析器複雜度。