jq 是切片、過濾與轉換 JSON 的標準命令列工具。它把一行命令變成處理 API 回應、log 檔案與設定的強大查詢語言。本教學涵蓋安裝、你每天會用到的核心 filter,以及一組針對最常見實際任務的可複製貼上 recipe。
什麼是 jq?
jq 從檔案或標準輸入讀取 JSON,套用一個 filter,再把 JSON(或純文字)寫到標準輸出。預設會格式化輸出,而且絕不會把你的資料送到任何地方 —— 它是個本地端二進位檔,處理敏感 payload 也很合適。
安裝 jq
# macOS
brew install jq
# Debian / Ubuntu
sudo apt-get install jq
# Windows (winget or choco)
winget install jqlang.jq
# 驗證
jq --versionIdentity Filter:隨手格式化
最簡單的 filter . 會原樣回傳輸入 —— 這就讓 jq 成了一個即時格式化工具:
# 格式化一個檔案
jq . data.json
# 格式化 curl 的回應
curl -s https://api.example.com/users | jq .
# 反過來壓縮(緊湊輸出)
jq -c . data.json選取欄位
用 .key 鑽進物件,用 [] 鑽進陣列:
echo '{"user":{"name":"Ada","age":36}}' | jq '.user.name'
# "Ada"
# 陣列的全部元素
echo '[{"id":1},{"id":2}]' | jq '.[]'
# {"id":1}
# {"id":2}
# 從每個陣列元素取出一個欄位
echo '[{"id":1,"name":"Ada"},{"id":2,"name":"Bob"}]' | jq '.[].name'
# "Ada"
# "Bob"
# 用 -r 去掉 JSON 的引號(raw output)
jq -r '.[].name' users.json用 select 過濾
# 只保留符合條件的物件
echo '[{"name":"Ada","active":true},{"name":"Bob","active":false}]' \
| jq '.[] | select(.active == true)'
# {"name":"Ada","active":true}
# 數值比較
jq '.[] | select(.age > 30)' users.json用 map 和物件建構來變形
# 把每個元素重新組合成新物件
echo '[{"id":1,"name":"Ada","email":"a@x.com"}]' \
| jq 'map({ userId: .id, label: .name })'
# [{"userId":1,"label":"Ada"}]
# 抽出一個扁平的值列表
jq '[.[].email]' users.json # ["a@x.com", ...]
# 用 | 把 filter 串起來
jq '.items | map(.price) | add' order.json # 所有價格之和常用 Recipe
| 任務 | 指令 |
|---|---|
| 格式化 | jq . file.json |
| 壓縮 | jq -c . file.json |
| 取一個欄位 | jq '.data.token' resp.json |
| Raw 字串(不帶引號) | jq -r '.token' resp.json |
| 計算陣列長度 | jq '. | length' list.json |
| 物件的所有 key | jq 'keys' obj.json |
| 過濾行 | jq '.[] | select(.active)' |
| 依欄位排序 | jq 'sort_by(.age)' |
| 加總一個欄位 | jq '[.[].amount] | add' |
| 排序物件的 key | jq --sort-keys . file.json |
| 驗證(透過 exit code) | jq empty file.json |
重塑物件:to_entries / from_entries
jq 裡兩個最有用的物件形狀變換工具:
# 重新命名每個 key(這裡轉小寫)
echo '{"Name":"Ada","Active":true}' \
| jq 'with_entries(.key |= ascii_downcase)'
# → {"name":"Ada","active":true}
# 丟掉值為 null 的 key
jq 'with_entries(select(.value != null))' file.json
# 物件 ⇄ 鍵值對陣列
jq 'to_entries' file.json # → [{"key":"name","value":"Ada"}, ...]
jq 'from_entries' pairs.json # → {"name":"Ada", ...}插值與輸出格式:\(.x)、@csv、@json、@base64
jq 內建字串插值與 格式字串,可以把 JSON 轉成其他格式:
# 在引號字串裡做字串插值
jq -r '"\(.user) bought \(.items|length) items"' order.json
# 每個物件一列 CSV
jq -r '.[] | [.id, .name, .total] | @csv' orders.json
# 內聯 JSON 給 shell 用(轉義過的字串字面值)
jq -r '.user | @json' record.json
# Base64 編碼一個值(處理 token / data URI 很方便)
jq -r '.payload | @base64' message.json
# 解碼這邊:較新版 jq 支援 @base64d用 jq 驗證 JSON
因為 jq 遇到非法輸入時 exit code 非零,jq empty file.json 是腳本與 CI 裡乾淨俐落的合法性檢查 —— 更多驗證方法見 如何驗證 JSON。
什麼時候瀏覽器工具更快
jq 在腳本與 pipeline 裡很出彩,但對於一次性的小事 —— 格式化貼過來的回應、檢視一個陌生的結構、修復壞掉的 JSON —— 瀏覽器工具不用安裝、也不用做 shell 轉義:
- JSON Fix —— 一步搞定格式化與修復
- JSON Viewer —— 把大回應當成可折疊的樹狀結構檢視
- 如何格式化 JSON —— 在程式碼裡與命令列裡格式化
常見問題
怎麼用 jq 格式化 JSON?
執行 jq . file.json —— identity filter . 回傳輸入,而 jq 預設會格式化輸出。要緊湊輸出就用 -c。
怎麼用 jq 抽出單一欄位?
用路徑 filter,例如 jq '.data.token',再加上 -r 就能拿到不帶引號的 raw 值。
怎麼用 jq 過濾 JSON 陣列?
用 .[] 走訪,再用 select(),例如 jq '.[] | select(.active == true)'。
jq 能驗證 JSON 嗎?
可以 —— jq empty file.json 解析輸入,如果非法就以非零 exit code 結束,在 CI 裡很實用。詳情見 如何驗證 JSON。
繼續閱讀
- 如何格式化 JSON —— jq、JavaScript、Python 與瀏覽器格式化
- 如何壓縮 JSON —— 用
jq -c等方式取得緊湊輸出 - 如何驗證 JSON —— 包括在 CI 裡用
jq empty - JSON Viewer —— 檢視 JSON 的瀏覽器替代方案