首页 > 解决方案 > 使用 jq 将 JSON 结构化为 CSV

问题描述

使用jq我尝试将 JSON 转换为 CSV。这是我的输入 JSON 的样子:

{
  "rows": [
    {
      "a": ["x","y"],
      "b": "some",
      "c": "string"
    },
    {
      "a": ["u","v"],
      "b": "another",
      "c": "string"
    }
  ]
}

所需的输出如下:

a   | b       | c
x y | some    | string
u v | another | string

编辑:对于那些抱怨这不是有效的 CSV 的人,这里是符合 RFC 4180 的语法:

a,b,c
x y,some,string
u v,another,string

使用.rows,我成功获得了数组:

[{"a":["x","y"],"b":"some","c":"string"},{"a":["u","v"],"b":"another","c":"string"}]

但是.rows | @csv说:object ({"a":["x","...) is not valid in a csv row。所以,我必须以某种方式加入键“a”中的数组。

使用.rows[] | .a | join(" ")我得到:

"x y"
"u v"

但是我如何将它返回到我的 JSON 中,然后... | @csv用来获取我想要的 CSV 数据?

标签: jsoncsvnestedexport-to-csvjq

解决方案


根据您的输入,以下程序:

.rows[]
| map_values(if type == "array" then join(" ") else . end)
| [.[]]
| @csv

产生逗号分隔值输出:

"x y","some","string"
"u v","another","string"

添加标题很简单,所以我将把它留给你。另外,让我指出,由于您指定了 CSV 输出,@csv因此强烈建议您使用,但如果由于某种原因您想避免使用那些有时是多余的引号,您可以使用字符串值来根据需要插入引号, 然后用join(",")代替@csv.

或者,您可能希望@tsv融入您的解决方案。

警告

上面的解决方案假定 a/b/c 键的顺序始终相同,并且对象没有其他键等。如果安全是一个问题,那么只需修改[.[]]程序中的行以准确指定您想要的内容。

也可以看看:

有关处理标头、确保一致性和通用性的一些想法,请参阅:

jq:对象不能是 csv 格式,只能是数组


推荐阅读