【问题标题】:how to convert json of this format to csv with jq如何使用 jq 将这种格式的 json 转换为 csv
【发布时间】:2021-04-19 14:51:13
【问题描述】:

我有一个这样格式化的 json 文件:

{"key1": "value1"}
{"key2": "value2"}
{"key3": "value3"}

我想将此 json 转换为 csv。但是,文件中所有对象的键都不相同。我有一个所有可能键的列表,但其中一些可能在任何 json 对象中丢失。因此,如果是这种情况,我只想为该列插入一个空值。

如何将这种格式的 json 文件转换为我想要的 csv?

更新: 这是一个名为 objects.json 的示例文件

{"key1": "value1", "key2": "value2"}
{"key1": "value3", "key2": "value4", "key3": "value5"}
{"key1": "value6", "key2": "value7", "key4": "value8"}

每个对象都在文件的新行上。

我有一个名为 allkeys.json 的 json 文件,其中包含一个包含所有可能具有空值的键的对象:

{"key1": null, "key2": null, "key3": null, "key4": null}

我想将 example.json 转换为包含所有列的 CSV 文件,并且对于任何缺少列的对象都有空值。

所以我想要的输出是:

key1,key2,key3,key4
value1,value2,,
value3,value4,value5,
value6,value7,,value8

【问题讨论】:

  • 请给出一个完整的示例,包括“所有可能的键的列表”和预期的输出,更严格地遵循minimal reproducible example 准则。
  • 那不是有效的 JSON。试试看HERE
  • @dawg 这是我们的数据输出方式,我可以选择使用 sed 轻松将其转换为包含所有对象的 json 数组,但不确定是否有必要

标签: json csv jq


【解决方案1】:

您需要读取文件中的所有数据以确定所有对象共有的一组键,然后输出这些键和值(如果对象包含它们)。在随后的过程中最容易吞食数据。

$ jq -sr '([.[] | keys[]] | unique) as $keys | $keys, (.[] | [.[$keys[]]]) | @csv' input.json
"key1","key2","key3"
"value1",,
,"value2",
,,"value3"

jqplay

【讨论】:

  • OP 说“我有一个所有可能键的列表”,所以不需要啜饮。即使必须从 JSON 中推断出密钥,两遍解决方案也可以替代 slurping....
【解决方案2】:

我有一个所有可能键的列表

假设此列表可用作 JSON 字符串数组,例如作为$keys。那么使用下面的 jq 过滤器有几个优点,包括效率(不使用 -s 选项)和不丢失数据(相对于 $keys):

$keys, (inputs | [.[$keys[]]]) | @csv

示例用法:

< input.json jq -nr --argjson keys '["key1","key2","key3","key4"]' -f program.jq
   

输出

"key1","key2","key3","key4"
"value1",,,
,"value2",,
,,"value3",

两遍解决方案

如果必须从数据中推断出密钥,则可能仍然值得考虑两遍解决方案,因为这样可以避免“破坏”数据。无论如何,如果采用双通道解决方案,则上述解决方案可以用于第二部分,第一部分如下:

jq -nc 'reduce inputs as $x (null; . + $x) | keys_unsorted' input.json

因此,在类似 bash 的环境中,您将拥有:

<input.json jq -nr \
  --argjson keys "$(< input.json jq -nc 'reduce inputs as $x (null; . + $x) | keys_unsorted')" '
   $keys, (inputs | [.[$keys[]]]) | @csv
'

【讨论】:

  • 它不是特定于 bash 的;它也应该在 sh 中按原样工作,因此也可能在其他地方工作。
【解决方案3】:

如果正确理解了问题,您可以做的是将所有键设置为 null 的 json 文件,然后将其与缺少键的文件合并。然后,您将拥有一个包含所有密钥的新 json 文件,稍后您可以像往常一样将其转换为 csv。这可以使用jq add 来完成,如下例所示:

echo '{"key1":null}{"key2":null}{"key3":null}{"key4":null}{"key5":null}' > allkeys.json

echo '{"key1":"value1"}{"key2":"value2"}{"key3":"value3"}' > update.json

jq -s add allkeys.json update.json

输出:

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "key4": null,
  "key5": null
}

将转换添加到 csv:

jq -s add allkeys.json update.json | jq -r  '[.[]] | @csv'

输出:

"value1","value2","value3",,

【讨论】:

  • 我按照你说的做了,它合并了键,但是当我尝试转换为 csv 时,它不会为空列添加逗号。你知道这是怎么做到的吗?
  • @fraoudas:管道进入[.[]] | @csv
  • @fraoudas,如 peak 所述,然后您可以将结果通过管道传输到 csv。我已更新答案以包含转换步骤。
  • 我错了,当我合并键时,它只对文件中的一个对象这样做。结果,当我将它通过管道传输到 csv 时,只有一行。你知道这是为什么吗?
  • 请用 json 文件的样本和所需的输出更新问题,我们会解决的
猜你喜欢
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多