【问题标题】:JQ - Denormalize nested objectJQ - 非规范化嵌套对象
【发布时间】:2020-05-06 12:45:13
【问题描述】:

我一直在尝试将一些 JSON 转换为 csv,但遇到以下问题:

我有以下输入 json:

{"id": 100, "a": [{"t" : 1,"c" : 2 }, {"t": 2, "c" : 3 }] }
{"id": 200, "a": [{"t": 2, "c" : 3 }] }
{"id": 300, "a": [{"t": 1, "c" : 3 }] }

我希望得到以下 CSV 输出:

id,t1,t2
100,2,3
200,,3
300,3,

不幸的是,如果其中一个选择不匹配,JQ 不会输出。 示例:

echo '{ "id": 100,  "a": [{"t" : 1,"c" : 2 }, {"t": 2, "c" : 3 }] }' | jq '{t1: (.a[] | select(.t==1)).c , t2: (.a[] | select(.t==2)).c }'

输出:

{ "t1": 2,  "t2": 3   }

但如果其中一个对象 select 返回不匹配,则它根本不会返回。 示例:

echo '{ "id": 100,  "a": [{"t" : 1,"c" : 2 }] }' | jq '{t1: (.a[] | select(.t==1)).c , t2: (.a[] | select(.t==2)).c }' 

预期输出:

{ "t1": 2,  "t2": null   }

有谁知道如何使用 JQ 实现这一目标?

编辑:

根据@peak 的评论,我找到了我正在寻找的解决方案。

jq -r '["id","t1","t2"],[.id, (.a[] | select(.t==1)).c//null, (.a[] | select(.t==2)).c//null ]|@csv'

替代运算符完全符合我的要求。 Alternative Operator

【问题讨论】:

  • 请同时描述基本要求,以便其他人更容易受益。

标签: json export-to-csv jq


【解决方案1】:

这是一个简单的解决方案,它不假设任何关于 .a 数组中项目的顺序,并且可以轻松推广到任意多个 .t 值:

# Convert an array of {t, c} to a dictionary:
def tod: map({(.t|tostring): .c}) | add;

["id", "t1", "t2"],   # header
(inputs 
 | (.a | tod) as $dict
 | [.id, (range(1;3) as $i | $dict[$i|tostring]) ])
| @csv

命令行选项

使用 -n 选项(因为正在使用 inputs)和 -r 选项(生成 CSV)。

【讨论】:

  • 我几乎在我的答案中添加了“等待@peak 产生三分之一大小的东西”。
  • @peak: 无论如何我可以修复jq -r '["id","t1","t2"],[.id, (.a[] | select(.t==1)).c//null, (.a[] | select(.t==2)).c//null ]|@csv' json 以避免多次打印标题?
  • @Inian - 最简单的方法是使用inputs
  • @peak 感谢您的评论。它帮助我找到了答案。
【解决方案2】:

这绝对是一团糟,但它确实有效:

$ cat tmp.json
{"id": 100, "a": [{"t" : 1,"c" : 2 }, {"t": 2, "c" : 3 }] }
{"id": 200, "a": [{"t": 2, "c" : 3 }] }
{"id": 300, "a": [{"t": 1, "c" : 3 }] }
$ cat filter.jq
def t(id):
  .a |
  map({key: "t\(.t)", value: .c}) |
  ({t1:null, t2:null, id:id} | to_entries) + . | from_entries
  ;

inputs |
  map(.id as $id | t($id)) |
  (.[0] | keys) as $hdr |
  ([$hdr] + map(to_entries |map(.value)))[]|
  @csv
$ jq -rn --slurp -f filter.jq tmp.json
"id","t1","t2"
2,3,100
,3,200
3,,300

简而言之,您生成一个包含输入值的直接对象,然后将其添加到“默认”对象以填充缺失的键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-02
    • 2019-10-11
    • 2019-09-04
    • 2021-03-19
    • 1970-01-01
    • 2017-12-23
    • 2016-11-15
    • 2018-03-02
    相关资源
    最近更新 更多