求助:如何用JQ将嵌套JSON转换为指定格式CSV?
问题描述
我之前试过用JQ处理JSON转CSV的方法,想套用到更大的JSON文件里但没成功。现在需要把下面的嵌套JSON转换成指定格式的CSV,但搞不定子嵌套数组的处理,求解释和解决办法。
给定JSON:
[ {"field": "F1","results": [{"details": [ {"name": "P1","matches": [ {"displayName": "User1","smtpAddress": "user1@foo.bar"}, {"displayName": "User2","smtpAddress": "user2@foo.bar"} ] }, {"name": "P2","matches": [ {"displayName": "User3","smtpAddress": "user3@foo.bar"}, {"displayName": "User4","smtpAddress": "user4@foo.bar"} ] }]}]}, {"field": "F2","results": [{"details": [ {"name": "P3","matches": [ {"displayName": "User1","smtpAddress": "user1@foo.bar"}, {"displayName": "User5","smtpAddress": "user5@foo.bar"} ] }, {"name": "P4","matches": [ {"displayName": "User6","smtpAddress": "user6@foo.bar"}, {"displayName": "User7","smtpAddress": "user7@foo.bar"} ] }]}]} ]
期望CSV格式:
"F1","P1","User1 <user1@foo.bar>;User2 <user2@foo.bar>" "F1","P2","User3 <user3@foo.bar>;User4 <user4@foo.bar>" "F2","P3","User1 <user1@foo.bar>;User5 <user5@foo.bar>" "F2","P4","User6 <user6@foo.bar>;User7 <user7@foo.bar>"
解决方案
JQ命令:
jq -r ' .[] | .field as $field | .results[].details[] | .name as $name | .matches | map("\(.displayName) <\(.smtpAddress)>") | join(";") as $matches_str | [$field, $name, $matches_str] | @csv ' input.json
步骤解释:
- 遍历顶层数组:
.[]逐个处理每个包含field和results的对象。 - 保存顶层字段值:
.field as $field把当前对象的field值存为变量,后续复用。 - 深入嵌套结构:
.results[].details[]钻到results数组的第一个元素里的details数组,遍历每个details对象。 - 保存子项名称:
.name as $name把当前details对象的name存为变量。 - 处理matches数组:
map("\(.displayName) <\(.smtpAddress)>")把每个matches对象转换成"用户名 <邮箱>"的格式。join(";")把转换后的字符串用分号拼接成一个整体。
- 生成CSV行:把
$field、$name、$matches_str组成数组,用@csv格式化成符合要求的CSV行,-r参数输出原始字符串(不带JSON引号)。
失败原因分析
大概率是没正确逐层遍历嵌套数组,或者没把上层的field、name变量传递到子层级。这个方案通过变量绑定(as $xxx)保留了上层需要的字段值,同时用map专门处理matches数组的格式化,逻辑分层清晰,能适配更大的JSON文件。
内容的提问来源于stack exchange,提问作者CD007
相关产品推荐
相关产品推荐

