jq 是切片、过滤和转换 JSON 的标准命令行工具。它把一行命令变成处理 API 响应、日志文件和配置的强大查询语言。本教程涵盖安装、你每天会用到的核心 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 |
| 校验(通过退出码) | 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 遇到非法输入时退出码非零,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 解析输入,如果非法就以非零退出码退出,在 CI 里很好用。详情见 如何校验 JSON。
继续阅读
- 如何格式化 JSON —— jq、JavaScript、Python 和浏览器格式化
- 如何压缩 JSON —— 用
jq -c等方式得到紧凑输出 - 如何校验 JSON —— 包括在 CI 里用
jq empty - JSON Viewer —— 浏览 JSON 的浏览器替代方案