
本文详解如何使用 jq 工具从结构化 JSON 中提取指定字段(如 .Columns[].Id 作为 CSV 表头、.Rows[].Values 作为数据行),生成标准 CSV 输出,兼顾可读性、健壮性与实际工程需求。
本文详解如何使用 jq 工具从结构化 JSON 中提取指定字段(如 `.Columns[].Id` 作为 CSV 表头、`.Rows[].Values` 作为数据行),生成标准 CSV 输出,兼顾可读性、健壮性与实际工程需求。
在数据处理与 ETL 场景中,常需将 API 返回的嵌套 JSON(如报表服务响应)快速转为 CSV 供 Excel 或下游系统消费。本例 JSON 具有典型二维表结构:Columns 数组定义字段元信息(含 Id 字段作为逻辑列名),Rows 数组以 Values 列表形式存储每行原始值。目标是忽略 QueryHandle、RowCount 等无关字段,仅导出纯净 CSV。
✅ 核心 jq 命令解析
最简洁有效的解决方案如下:
jq -r '[.Columns[].Id], (.Rows[].Values) | @csv' input.json
- -r:启用原始输出模式(raw output),避免 JSON 字符串额外引号包裹;
- [.Columns[].Id]:构造表头数组,提取所有 Columns 对象的 Id 值(["ItemName","Date","Qty"]);
- (.Rows[].Values):展开 Rows 数组,逐项输出其 Values 子数组;
- | @csv:将上游每个输入数组(表头 + 每行数据)自动格式化为 RFC 4180 兼容的 CSV 行(自动转义、加引号、逗号分隔)。
执行后输出:
"ItemName","Date","Qty" "ITEM1","10-MAY-2024","100" "ITEM2","20-MAY-2024","200" "ITEM3","30-MAY-2024","400"
⚠️ 注意事项与进阶技巧
大小写标准化:若需将表头转为 PascalCase 或全小写,可在提取后链式处理:
jq -r '[.Columns[].Id | ascii_upcase], (.Rows[].Values) | @csv' input.json # 输出:"ITEMNAME","DATE","QTY"
空值/缺失字段防护:当 Rows[].Values 长度不一致时,@csv 仍能安全输出(不足位补空字符串),但建议预先校验:
jq -r 'if (.Rows | length) == 0 then [(.Columns[].Id)] else [(.Columns[].Id)], (.Rows[].Values) end | @csv' input.json
Python 备选方案(无 jq 环境):
若需跨平台或集成到 Python 脚本中,可使用标准库 json + csv:import json, csv, sys with open("input.json") as f: data = json.load(f) headers = [col["Id"] for col in data["Columns"]] rows = [r["Values"] for r in data["Rows"]] writer = csv.writer(sys.stdout, quoting=csv.QUOTE_MINIMAL) writer.writerow(headers) writer.writerows(rows)
✅ 总结
该方案以声明式思维直击 JSON 结构本质:用数组聚合表头,用流式展开处理行数据,交由 @csv 完成标准化序列化。相比通用转换工具(如 jq '.[] | @csv'),它精准控制字段来源,规避了嵌套层级误解析风险,是处理“带元数据的表格型 JSON”的最佳实践。推荐在 CI/CD 流水线、运维脚本或数据清洗任务中直接复用。