YAML JSON 比較 — 先講結論
一句話:API 或系統之間的資料交換用 JSON,人會動手編輯的設定檔用 YAML。兩種格式表達的是同一套資料模型(物件、陣列、字串、數值、布林值),但 JSON 嚴格且冗長,YAML 以縮排為基礎、支援註解,可讀性較高。
| JSON | YAML | |
|---|---|---|
| 語法 | 大括號與方括號 | 縮排(空白) |
| 註解 | 不支援 | 支援(#) |
| 主要用途 | REST API、資料交換 | 設定檔(Kubernetes、GitHub Actions) |
| 可讀性 | 對機器友善 | 對人友善 |
| 嚴格程度 | 嚴格 | 寬容(型別隱含推斷) |
重點摘要
- JSON 嚴格、快速、適合機器處理;YAML 以縮排呈現、對人友善、可加註解
- REST API、日誌串流、高吞吐處理選 JSON;Kubernetes、GitHub Actions、Ansible 等人手編輯的設定檔選 YAML
- YAML 支援註解、錨點、多行字串、日期型別,JSON 沒有
- LLM prompt 中,YAML 比帶縮排的 JSON 大約少 20% token(本站實測 -22%)。但若是去除所有空白的 compact JSON,順序會翻轉,JSON 反而更省。JSON 解析更快,對不受信任的輸入也更安全
這篇文章會依序講解語法差異、同一份資料在兩種格式中的寫法、實務上的選用標準、轉換時常見的陷阱。2026 年以来越來越常被問到的「餵給 LLM 時哪種格式 token 成本較低」也會一併涵蓋。
想拿自己的設定檔兩種格式對比一下的話,先把 YAML 貼到 YAML to JSON 轉換器 轉成 JSON,再把結果貼回去看同一份資料來回轉了幾次之後變成什麼樣子。整個處理在瀏覽器內完成,資料不會上傳到外部伺服器。
實務中的使用場景
進入語法細節之前,實務上「到底選哪種」基本就是下面這個模式:
- Kubernetes manifest、Helm chart — YAML
- Docker Compose 檔案 — YAML
- GitHub Actions、GitLab CI、CircleCI 管線設定 — YAML
- Ansible playbook — YAML
- REST API 的 request / response body — JSON
package.json、composer.json、瀏覽器與伺服器之間的通訊 — JSON- 日誌記錄與事件串流 — JSON Lines
- OpenAPI / Swagger 規格 — YAML 或 JSON(作者通常用 YAML 寫,工具產出 JSON)
規律很清楚:人讀、人編輯的檔案用 YAML,程式生成與消費的資料用 JSON。在格式選擇上猶豫時,拿這句話當判斷標準最實際。
語法並列比較
用同一份 web server 設定分別以兩種格式寫出來:
YAML:
# Web server 設定
server:
host: localhost
port: 8080
debug: true
allowed_origins:
- https://example.com
- https://staging.example.com
headers:
X-Frame-Options: DENY
Strict-Transport-Security: "max-age=31536000"
JSON:
{
"server": {
"host": "localhost",
"port": 8080,
"debug": true,
"allowed_origins": [
"https://example.com",
"https://staging.example.com"
],
"headers": {
"X-Frame-Options": "DENY",
"Strict-Transport-Security": "max-age=31536000"
}
}
}
有兩點值得注意。第一,YAML 版本因為省去了大部分括號與引號,字元數較少——上面兩段分別數一數,YAML 是 232 字、JSON 是 291 字,相差約 20%(若把 JSON 無法承載的註解行排除,差距約 25%)。第二,只有 YAML 版本能保留頂端的 # Web server 設定 這行註解,轉成 JSON 之後這條資訊就消失了。如果要從零開始學 YAML 的縮排與型別規則,可參考 YAML 語法教學。
資料型別:YAML 有而 JSON 沒有
兩種格式都支援字串、數值、布林值、null、物件、陣列。YAML 額外加了幾樣對撰寫設定檔很方便型別。
日期與時間戳
YAML 解析器把 ISO 8601 格式的日期當作一等的值來處理:
release_date: 2026-04-01
created_at: 2026-04-01T09:30:00Z
JSON 沒有日期型別,只能當字串處理,接收端需要自行解析:
{
"release_date": "2026-04-01",
"created_at": "2026-04-01T09:30:00Z"
}
多行字串
YAML 有兩種專用的多行記法。literal block(|)保留換行,folded scalar(>)把換行折成空白:
description: |
這個服務會接收 GitHub 的 webhook
並轉送到內部佇列。
summary: >
所有流量都經過 Cloudflare 代為處理,
來源伺服器限制在 100 rps。
JSON 要表達相同內容,就得在一行內用 \n 逸出換行:
{
"description": "這個服務會接收 GitHub 的 webhook\n並轉送到內部佇列。\n",
"summary": "所有流量都經過 Cloudflare 代為處理,來源伺服器限制在 100 rps。"
}
寬鬆的型別推斷
YAML 會嘗試從未加引號的值推斷型別。視規格版本不同,yes、no、on、off 可能被解讀為布林值,看起來像數值的會被當成數值。人寫的時候方便,但也是意外 bug 的來源。最著名的例子是「挪威問題」(Norway problem):country: NO 被解析成布林值 false。JSON 沒有這個歧義——字串永遠加引號,所有型別都是明確的。
註解:YAML 在設定檔上的優勢
YAML 的註解從 # 開始一直到行末。要記錄「為什麼要有這個設定值」或「有什麼限制」時非常方便:
retries: 3 # 再高就會超過上游服務的 timeout
JSON 標準(RFC 8259)沒有註解語法。常见的因應方式包括放一個 "_comment": "..." 的 dummy 欄位,或使用非標準的 JSONC、JSON5。這些規避手段之所以存在,正是因為 JSON 缺少註解這個限制。JSON 註解的各種替代方法,整理在 JSON 註解方式。
錨點與別名:YAML 的重用機制
YAML 允許你把一個值定義一次,在其他位置用參考來引用。& 定義錨點,* 引用別名,<<: 合併鍵則把共用的區塊拉進當前的 mapping:
defaults: &defaults
adapter: postgres
host: db.internal
pool: 5
development:
<<: *defaults
database: myapp_dev
production:
<<: *defaults
database: myapp_prod
pool: 20
轉成 JSON 之後,錨點會被展開成 inline,development 和 production 各自複製一份完整的預設值。資料本身正確,但「這兩個環境共用同一組預設值」的原始意圖在 JSON 結構中就不再可見了。
效能與檔案大小
從機器間資料傳輸的角度看,JSON 明顯更快。各主流語言的 runtime 都內建高度最佳化的 JSON 解析器(JSON.parse、json.loads、encoding/json)。YAML 的語法較複雜、規則也有歧義,解析速度較慢,且多數 YAML 函式庫內部仍然要構建一棵與 JSON 等價的樹。
檔案大小要看「跟哪種 JSON 比」。用 token 測量時同一份 32 行樣本(scripts/benchmarks/yaml-vs-json-tokens/)實測,YAML 是 667 bytes,帶縮排的 JSON 是 857 bytes,YAML 約小 22%。但把換行與空白全部去掉的 compact JSON 是 686 bytes,跟 YAML 幾乎一樣。如果傳輸前經過 gzip 壓縮,這個差距也會趨近消失。YAML 真正的成本不在 bytes,而在解析時的 CPU 時間,以及隱含型別推斷引發的預期外行為。
應該選 YAML 的情況
- 檔案是人會讀、會動手編輯的
- 檔案是設定檔而非資料 payload
- 需要註解來說明設定的意圖
- 工具鏈已經假設是 YAML(Kubernetes、Docker Compose、Ansible、CI/CD)
- 想用錨點和別名減少重複
手上有一份 JSON 設定檔想改寫成更易讀的格式,可以把它貼到 YAML to JSON 轉換器 反向查看巢狀結構在縮排下長什麼樣子。
不該選 YAML 的情況
看起來 YAML 很適合,但實際上副作用更大的情境:
- 程式自動生成的設定檔 — 型別推斷會把
version: 2.0變成數值2,資料被靜默篡改 - 即時高吞吐資料串流 — 解析 overhead 累積起來對處理量有影響
- 安全性上不可信的外部輸入 — YAML 標籤如
!!python/object在 unsafe loader 中可以執行任意程式碼,務必使用yaml.safe_load等安全 loader - 短且扁平的單一層級資料 — 縮排帶來的簡潔感消失,JSON 反而更直觀
應該選 JSON 的情況
- 資料由程式生成、由程式消費
- 需要跨語言互通且要避免意外的型別轉換
- 透過 API 或網路傳輸資料
- 要求解析結果嚴格、沒有歧義
- 效能優先,需要解析速度快且可預測
人寫的 YAML 要交給只認 JSON 的程式處理,在實務上非常常見。把 YAML 貼到 YAML to JSON 轉換器 可以即時看到語法錯誤的行號,也能預先檢查哪些值可能因為型別推斷而變形。
決策矩陣:YAML 與 JSON 一頁看清
把上面的選用標準濃縮成一張表。左欄找到你的情境,讀該行的判定即可。
| 判斷標準 | YAML | JSON |
|---|---|---|
| 人會動手編輯 | 適合 — 符號少、可寫註解 | 不適合 — 符號多、無註解 |
| 系統間資料交換 | 不適合 — 解析慢、型別有歧義 | 適合 — 內建高速解析器 |
| 需要註解 | 正式支援(#) | 不支援(JSONC/JSON5 是非標準規避) |
| 檔案內值重用 | 支援錨點、別名、合併鍵 | 不支援 — 只能重複或改結構 |
| 型別行為 | 隱含推斷,依解析器而異(見下方實測表) | 所有環境下嚴格一致 |
| 解析器取得性 | 多數語言需外部函式庫 | 所有主流 runtime 內建 |
| 單檔多文件 | 支援(--- 分隔) | 不支援 — 一檔一個值 |
| 多行字串 | 專用語法(|、>) | 一行內用 \n 逸出 |
| LLM token 成本 | 比帶縮排的 JSON 少 | compact JSON 最少 |
| 主要活動範圍 | Kubernetes、CI/CD、Docker Compose、設定檔 | API、日誌、資料管線、儲存 |
YAML 轉 JSON 時的陷阱
轉換大多是無損的,但有幾個邊界狀況需要留意:
- 註解消失 — JSON 沒有註解語法,所有
#開頭的行都會被移除 - 錨點展開 — 共用區塊變成在各位置重複的資料
- 日期變字串 — ISO 格式的日期失去型別資訊
- 型別推斷的意外結果 —
version: 2.0在 JSON 中可能變成數值2 - 多文件處理 —
---分隔的多個 YAML 文件無法放入單一 JSON 檔案,得選一個或包在外層陣列裡 - 重複鍵 — YAML 的重複鍵行為依實作而異,JSON 中只有最後一個值保留
- 標籤與自訂型別 — YAML 的
!!timestamp或自訂標籤在 JSON 中沒有對應
實測:同一份 YAML 給 4 種解析器得到 4 種結果
「型別推斷的意外結果」在親眼看到同一行 YAML 經過不同函式庫後變成不同值之前,很難有實際感受。把一組含糊的 scalar 值餵給 4 種主流解析器(js-yaml 4.1.1、yaml/eemeli 2.8.3、PyYAML 6.0.3 safe_load、ruamel.yaml 0.19.1)實測(重現腳本與原始資料在 scripts/benchmarks/yaml-parser-differences/,2026-07-10 於 Apple M5 Pro 環境量測)。轉換後實際進入 JSON 的值如下:
| 未加引號的 YAML 值 | js-yaml 4.1.1 | yaml (eemeli) 2.8.3 | PyYAML 6.0.3 | ruamel.yaml 0.19.1 |
|---|---|---|---|---|
NO(挪威問題) | "NO" | "NO" | false | "NO" |
on | "on" | "on" | true | "on" |
010(舊式 8 進制) | 10 | 10 | 8 | 10 |
0o10(YAML 1.2 的 8 進制) | 8 | 8 | "0o10" | 8 |
1:30(60 進制) | "1:30" | "1:30" | 90 | "1:30" |
2026-07-10(裸日期) | Date 物件 | "2026-07-10" | date 物件 | date 物件 |
a: 1 + a: 2(重複鍵) | 報錯 | 報錯 | 後值優先(2) | 報錯 |
<<: *base(合併鍵) | 正常合併 | 保留 literal "<<" 鍵 | 正常合併 | 正常合併 |
從轉換實務的角度,有三個發現值得注意。
第一,挪威問題不是「YAML 整體的缺陷」。4 種解析器中,把 NO 轉成 false 的只有走 YAML 1.1 系的 PyYAML,其餘 3 種遵循 YAML 1.2 的解析器都保留字串 "NO"。
第二,裸日期分成三種行為。eemeli 的 yaml 回傳純字串,js-yaml、PyYAML、ruamel.yaml 則產生日期物件,後續的 JSON 序列化過程需要額外處理格式。
第三,合併鍵 <<: 在 eemeli yaml 預設設定下行為不同。它不會合併共用區塊,而是在 JSON 輸出中留下一個 literal 的 "<<" 鍵——這種資料腐化要到下游服務開始出錯才會被發現。
如果管線中使用的解析器不是你選的,在轉換前把含糊的值("NO"、"1:30"、"2026-07-10")先用引號包起來是最安全的做法。把有代表性的檔案貼到 YAML to JSON 轉換器 中,就能在部署到生產環境之前、在瀏覽器內確認每個值會變成什麼。
完整的轉換陷阱清單與處理方式,整理在 YAML 轉 JSON 指南。轉換後的 JSON 想整理得更易讀,可參考 JSON 排版線上工具。
用 FormatArc 做 YAML ⇄ JSON 轉換
FormatArc 的所有轉換都在瀏覽器內完成。不需要上傳檔案、不需要註冊帳號,資料不會離開你的裝置。


- YAML to JSON — 貼上 YAML 得到 JSON,語法錯誤會標出行號
- 腳本或自動化管線中處理的話,yq在新分頁中開啟 或 Python 的
yaml.safe_load是常用選擇。Python 一行指令:
python3 -c "import yaml,json,sys; print(json.dumps(yaml.safe_load(sys.stdin),indent=2))" < config.yaml
常見問題
YAML 是 JSON 的上位集合嗎?
從 YAML 1.2 規格開始,合法的 JSON 文件也可以被直接解析為合法的 YAML。也就是說 YAML 解析器能讀 JSON 檔案,但反向不行——JSON 解析器讀不了 YAML。另外,實務上許多 YAML 函式庫仍然預設走舊版的 YAML 1.1,相容性並非百分之百。
Kubernetes 和 Docker Compose 為什麼用 YAML 而不是 JSON?
因為這些設定檔是給人讀、給人編輯的。以縮排為基礎加上支援註解的 YAML,在維護大量基礎設施設定時對人更友善。需要輸出狀態時(例如 kubectl get ... -o json),會另外提供給機器用的 JSON 模式。
YAML 解析比 JSON 快嗎?
不是。JSON 解析在所有主流語言中都明顯更快。JSON 解析器經過高度最佳化,YAML 則因為語法更複雜、規則有歧義而較慢。效能敏感的資料傳輸場景中,JSON 是正確的選擇。
JSON 轉 YAML 會丟資料嗎?
通常不會。JSON 功能較少,JSON → YAML 幾乎都是無損的。你無法加上 JSON 原本沒有註解,但資料本身可以完整地來回轉換。Kubernetes、Docker Compose、Ansible 等實務場景中 JSON 轉 YAML 的寫法,可參考 JSON 轉 YAML 比較。
YAML 中寫了 country: NO 為什麼會變成 false?
這就是有名的「挪威問題」。舊版 YAML 解析器(YAML 1.1 規格)會把未加引號的 NO 解讀為布林值 false。改成 country: "NO" 就能解決。YAML 1.2 規格已經移除了這個行為,但許多工具預設仍然走 1.1。
餵給 LLM prompt 時,YAML 和 JSON 哪個 token 效率較高?
結論取決於「比較對象的 JSON 是怎樣的」。本站用 32 行的 Kubernetes 風格樣本(scripts/benchmarks/yaml-vs-json-tokens/)以 OpenAI 的 tiktoken 實測。
跟帶縮排的 JSON(json.dumps(data, indent=2))比,YAML 在 cl100k_base 和 o200k_base 兩種編碼下都大約少 22% token(YAML 218 tokens vs 帶縮排 JSON 281 tokens)。
但跟去除所有空白與換行的 compact JSON(json.dumps(data, separators=(",", ":")))比,結果翻轉,JSON 大約少 18〜21% token(compact JSON 180 tokens)。
巢狀很深的 JSON 會把每一個 {、}、[、]、" 都當獨立 token 消耗,YAML 則以縮排表示階層、不需要閉合括號。JSON 一旦去掉空白,差距就補上了。
實務上的判斷標準:
- 可以傳 compact JSON 的話,JSON 最省
- 需要人一起審閱的設定檔、或包含多行字串的資料,YAML 可讀性高且整體成本較低
- 某些模型對嚴格 JSON 結構的遵循度較高,2026 年目前「輸入用 YAML、輸出要求 JSON」的非對稱模式被廣泛採用
YAML 的註解轉成 JSON 之後還保留嗎?
不保留。註解是綁定在檔案行位置上的文字資訊,一旦被解析成結構化資料物件就丟掉了。轉成 JSON 之後沒有辦法還原,如果註解重要就保留原本的 YAML 檔案。
總結
- YAML 與 JSON 表達的是同一套資料模型,差異在於「誰在讀」
- 人動手編輯的設定檔選 YAML,系統與程式之間的資料通信選 JSON
- 轉換時留意型別推斷、錨點展開、註解消失這三件事
- 把 YAML 貼到 FormatArc 的轉換器中就能在瀏覽器內即時檢查,不用把資料送到任何伺服器