提示

JSON 工具集从入门到顺手:我自建了一套命令行数据处理流水线

日常开发中总跟 JSON 打交道:看日志里的单行 JSON 看着眼瞎,找两个 API 返回的差异找到眼花,把 JSON 转成 CSV 给运营同事折腾半天,还有那些带转义的字符串拷来拷去……后来我自己写了一套命令行脚本,把四个常用功能集成到一起。这篇文章不讲复杂理论,直接给命令、给例子、给踩坑记录。

一、为什么要自己折腾 JSON 工具

  • 推荐在线json工具https://www.viddown.cn/tools/json/editor/
    以下是离线版工具
  • 命令行里处理 JSON,用 jq 能格式化,但对比差异、转换格式还得翻文档。
  • 批量处理几十个 JSON 文件,用 GUI 点来点去不如一行脚本。

所以我自己维护了一个 json-tools 目录,里面放了几个脚本和一个 jq 的常用命令速查。

二、工具清单

功能 命令行实现 依赖
格式化 / 美化 / 压缩 jq jq
差异对比 jddiff <(jq . a.json) <(jq . b.json) jd / diff
格式转换(JSON ↔ CSV / XML / Python dict) jq + 内置脚本 jq, Python
字符串转义 / 反转义 python -c "import json; print(json.dumps/loads(...))" Python

三、安装依赖(老生常谈)

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install jq
# 差异对比工具 jd(更直观)
wget https://github.com/josephburnett/jd/releases/download/v1.8.0/jd-amd64-linux
chmod +x jd-amd64-linux
sudo mv jd-amd64-linux /usr/local/bin/jd

macOS

brew install jq
brew install jd

Windows

可以用 choco install jq,或者用 WSL。我一般直接在 WSL 里跑。

验证安装:

jq --version
jd --version

四、基础用法:每个功能怎么用

4.1 JSON 格式化 / 美化 / 压缩
美化(缩进 2 空格,排序 key):

cat ugly.json | jq '.' > pretty.json

压缩(去空格、换行):

cat pretty.json | jq -c '.' > minified.json

从 API 直接格式化:

curl -s https://api.example.com/data | jq '.'

踩坑:如果 JSON 里有不合法的 NaN 或 Infinity,jq 会报错。标准 JSON 不支持这些,需要先用 sed 替换成 null 或字符串。

4.2 JSON 差异对比
方法一:用 jd(推荐,彩色输出)

jd a.json b.json

输出类似:

diff
- ["name"]: "Alice"
+ ["name"]: "Bob"

方法二:用 jq + diff(系统自带)

diff <(jq -S . a.json) <(jq -S . b.json)

-S 对 key 排序,避免顺序不同误报差异。

踩坑:如果 JSON 很大,diff 输出不好读。jd 支持深度限制:jd -depth 2 a.json b.json,只看顶层差异。

4.3 格式转换
JSON ↔ CSV(适合表格数据)
假设有一个 users.json:

json
[{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]
转 CSV:

jq -r '.[] | [.name, .age] | @csv' users.json > users.csv

CSV 转 JSON(稍微复杂,用 Python 更稳):

python -c "import csv, json, sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < users.csv

JSON ↔ Python dict(用 Python 的 ast.literal_eval,常用于复制粘贴)

echo "{'name': 'Alice'}" | python -c "import sys, json, ast; print(json.dumps(ast.literal_eval(sys.stdin.read())))"

JSON ↔ XML(需要第三方工具 yq,它是 jq 的 XML 版)
安装 yq(支持 XML):

pip install yq

转 XML:

yq -x . input.json > output.xml

4.4 JSON 字符串转义 / 反转义
场景:日志里有一行 {"msg": "{\"a\":1}"},需要提取内部的 JSON。

反转义(把 \" 变成 ",然后解析):

echo '{"msg": "{\"a\":1}"}' | jq -r '.msg' | jq '.'

转义(把普通字符串转成可嵌入 JSON 的转义形式):

echo 'Hello "world"' | python -c "import sys, json; print(json.dumps(sys.stdin.read()))"

输出 "Hello \"world\"\n"。

更好的命令行工具:jq -R -s '.' 也可以对字符串进行 JSON 编码。

echo 'Hello "world"' | jq -R -s .

踩坑:jq -R(raw input)会把每行作为字符串,-s 把整个输入当作一个字符串。不加 -s 会每行输出一个 JSON 字符串。

五、实战:组合使用解决实际问题

  1. 格式化 + 对比两个 API 响应
curl -s api1 > /tmp/a.json
curl -s api2 > /tmp/b.json
jq . /tmp/a.json > /tmp/a.pretty
jq . /tmp/b.json > /tmp/b.pretty
jd /tmp/a.pretty /tmp/b.pretty
  1. 从日志中提取 JSON 字段并转 CSV
    假设日志每行是 2025-01-01 {"user": "alice", "score": 100}:
grep "user" app.log | cut -d' ' -f2 | jq -r '[.user, .score] | @csv' > report.csv
  1. 批量处理目录下所有 JSON 文件(压缩 + 备份)
for f in *.json; do
  jq -c . "$f" > "min/${f}"
done
  1. 把环境变量转成 JSON(比如配置注入)
env | grep "APP_" | jq -R 'split("=") | {key: .[0], value: .[1]}' | jq -s 'from_entries'

六、问题汇总(都是我真实遇到的)

  1. jq: error: Cannot index number with string
    原因:对非对象类型使用了 .field 语法,比如 jq '.name' 但输入是数组或数字。
    解决:先查看数据结构 jq '.',确认路径存在。

  2. jd 对比时提示 input not a valid YAML/JSON
    原因:文件编码问题(比如带 BOM),或者末尾有逗号。
    解决:用 jq . file > fixed 重新生成一遍,jq 会校验并输出标准格式。

  3. JSON 转 CSV 时字段缺失导致列不对齐
    原因:有些对象缺少某些字段,@csv 会输出空字符串,但列顺序是固定的。
    解决:先用 map 补齐缺失字段:

jq '[.[] | {name: .name, age: (.age // "unknown")}] | .[] | [.name, .age] | @csv' data.json
  1. 字符串转义后换行符变成了 \n 字面量
    场景:想把多行文本塞进 JSON,结果 Hello\nWorld 在 JSON 里变成 Hello\nWorld。
    原因:双重转义。
    解决:使用 jq -R -s 会正确保留换行符为 \n。

  2. diff <(jq . a) <(jq . b) 在 macOS 上报错
    原因:macOS 的 diff 不支持进程替换 <(...),但 zsh 支持。
    解决:改用 bash 执行,或者先输出临时文件。

  3. 大文件(几百 MB)用 jq 格式化会卡死
    原因:jq . 会把整个文件读入内存并格式化,大文件会 OOM。
    解决:使用 jq --stream 流式处理,或者只提取需要的字段:

jq -c '.field' huge.json > extracted.json

七、一点小建议

把常用命令写成 shell 函数放 .bashrc,例如:

jsonfmt() { jq '.' "$1" | bat -l json; }
jsondiff() { jd "$1" "$2"; }
jsoncsv() { jq -r '.[] | [.key1, .key2] | @csv' "$1"; }

对于 JSON 表达式测试,可以用 jq -n '{a:1,b:2}' 快速尝试语法,不需要临时文件。

遇到复杂的 JSON 处理(嵌套分组、聚合),先看 jq 的 group_by、reduce 函数,比写 Python 快。

永远不要在生产环境直接 curl | jq > 覆盖原文件。先写到临时文件,确认无误再 move。

最后推荐一个我每天用的 alias:

alias jq-pretty='jq . -S | bat -l json'

输出带语法高亮,养眼多了。

JSON 工具没有银弹,但 jq + jd + 一行 Python 能覆盖 90% 的需求。剩下的 10%,交给 Stack Overflow。

写完这篇,我把上面四个功能做成了四个独立脚本,丢在 ~/bin/ 下:
json-fmt
json-diff
json-convert
json-escape

顶部
×
🔖
收藏本站
将本站添加到浏览器书签,方便下次访问
Ctrl + D (Windows/Linux)
+ D (Mac)