壓縮與美化 JSON:時機與原因
空白不會改變 JSON 的語意,但會影響傳輸大小、可讀性與差異品質。本文整理何時壓縮、何時美化。
同一份資料的 12 KB JSON 與 4 KB JSON 語意上相同,只差在空白;但選哪 種寫法會實際影響傳輸大小、除錯難度、版本控制體驗,甚至 Content-Security-Policy 雜湊。本文是何時 壓縮、何時 美化 的 簡短回答,並附上兩端的工具。
壓縮與美化在做什麼
- 壓縮(minify)——把不在字串內的空白全部移除。換行、縮排、token 間的空格全沒了,結果是一行密密麻麻的 JSON。
- 美化(prettify / 別稱 beautify、pretty-print、format)——在 token 間插入換行與縮排,讓結構對人類可見。
Node 中:
const data = { a: 1, b: [2, 3] };
JSON.stringify(data); // '{"a":1,"b":[2,3]}'
JSON.stringify(data, null, 2); // '{\n "a": 1,\n "b": [\n 2,\n 3\n ]\n}'
第二個參數是 replacer(函式、陣列,或 null);第三個是 indent
(空格數,或 "\t" 之類字串)。
何時壓縮
當資料不會被人類讀到。最明確的情境:
- API 回應。每移除一個位元組就是一個位元組客戶端不用下載。對於數百 KB 的 payload 差異顯著;數 KB 以下則影響很小。
- Local storage / cookies。額度緊;空白是浪費。
- 資料庫中的 JSON / JSONB 欄位。儲存按位元組計費。
- 嵌在 HTML 的 JSON。
<script type="application/json">隨 HTML 出貨;SSR 框架(Next.js、Remix)已自動壓縮。 - 嵌在其他格式內的 JSON。塞進 SQL 字串或 YAML 欄位時,外層格式有自己的空白,你不需要再加。
何時美化
當人類會閱讀或比對:
- 除錯。檢視器裡漂亮的回應可以搜尋、可以折疊、可以掃讀;壓縮的就是一道牆。
- Code review。壓縮 JSON 的 diff 沒法看,因為改一個字就動到整行。美化後 diff 只顯示真正變更的行。
- 版控的設定檔。
package.json、tsconfig.json、fixture 都應美化。 - 給人看的日誌。(給日誌收集器吃的結構化日誌是 NDJSON 壓縮——見下節。)
- 文件與範例。美化是唯一可讀的形式。
它不改變語意,只動空白
JSON 對 token 之間的空白 不敏感。下面兩種形式解析後完全相同:
{"a":1,"b":[2,3]}
{
"a": 1,
"b": [2, 3]
}
因此:壓縮永遠不會改語意、美化永遠不會改語意,兩者可自由互轉。唯一 有意義的空白在 字串值內部,那些位元組必須原封不動。一個可信賴的 格式化器不會碰字串內容。
若「壓縮」結果與「美化」結果解析後不同,那就不是空白問題、是 bug。 JSON Formatter 雙向都無損; JSON Diff 會告訴你兩份文件不論格式是否真的不同。
Gzip / Brotli 與壓縮
常見問題:「我已經 gzip 了,還需要 minify 嗎?」
答案是有用,但邊際效益小。壓縮器最愛的就是重複的空白。典型 JSON 上:
- 原始(美化):100 KB
- 壓縮(minify):70 KB(省 30%)
- gzip 原始:12 KB
- gzip 壓縮:10 KB(再省 17%)
所以大型 payload 請同時 壓縮且 gzip——效益會疊加,只是非乘法。 數 KB 以下的小 payload,gzip 的封包開銷會吃掉節省,那 minify 就是唯 一有意義的動作。
NDJSON / 日誌串流是特例:每行壓縮,但行間以換行分隔。這是刻意取的 折衷,保留 grep 友善與多數壓縮效益。
實務流程
挑規則並一致套用:
- 儲存在 repo——美化。reviewer、未來的你、IDE 折疊都受惠。
- 送上線——壓縮、gzip。
- 日誌——NDJSON(每行壓縮的紀錄)。
- 除錯——dev tools 會自動美化壓縮回應,伺服端不必改。
動手試
把 payload 貼進 /zh-Hant/json/formatter, 切換美化(2 空格、4 空格、tab)或壓縮輸出。超過 ~1.5 MB 改用 Web Worker,UI 不會卡——串流式格式化參見 處理大型 JSON 檔案。
延伸閱讀
- 什麼是 JSON?——空白不會改變的語法規則。
- REST API 的 JSON 最佳實務——壓縮回應只是整體 API 設計的一部分。