【问题标题】:how do you use jq to create a columns based on objects and list other objects from same array under it for json to convert to csv?您如何使用 jq 基于对象创建列并列出其下同一数组中的其他对象,以便将 json 转换为 csv?
【发布时间】:2020-05-17 23:54:48
【问题描述】:

晚安社区,

我是 jq 的新手,我正在尝试将它用作将 json 输出转换为 csv 的工具。

我有以下情况。我想将下面列出的 json 数据转换为格式良好的 csv 文件,以便在 json 可以提供的格式之外进行其他编辑和审核过程。

我有以下 json 数据:

{
"enrollments": [
    {
        "adminContact": {
            "email": "admin@domain.com",
            "firstName": "john",
            "lastName": "doe",
            "phone": "555-555-5555"
        },
        "certificateType": "third-party",
        "changeManagement": true,
        "csr": {
            "c": "US",
            "cn": "www.column.com",
            "l": "Houston",
            "o": "A Company International Ltd.",
            "ou": "Technology and Operations Services",
            "sans": [
                "example1.com",
                "example2.com",
                "example3.com",
                "example4.com"
            ],
            "st": "Bermingham"
        }
    },
    {
        "adminContact": {
            "email": "admin@domain.com",
            "firstName": "john",
            "lastName": "doe",
            "phone": "555-555-5555"
        },
        "certificateType": "third-party",
        "changeManagement": true,
        "csr": {
            "c": "US",
            "cn": "www.column2.com",
            "l": "Houston",
            "o": "A Company International Ltd.",
            "ou": "Technology and Operations Services",
            "sans": [
                "www.example1.com",
                "www.example2.com",
                "www.example3.com",
                "www.example4.com"
            ],
            "st": "Bermingham"
        },
        "certificateType": "third-party",
        "changeManagement": true,
        "csr": {
            "c": "US",
            "cn": "www.column-other-additional-iterations.com",
            "l": "Houston",
            "o": "A Company International Ltd.",
            "ou": "Technology and Operations Services",
            "sans": [
                "www.example-to-infinite1.com",
                "www.example-to-infinite2.com",
                "www.example-to-infinite3.com",
                "www.example-to-infinite4.com"
            ],
            "st": "Bermingham"
    }
]
}

我的目标是将其转换为以下格式的 .csv 文件。我希望能够抓住任何出现的“cn”及其相应的“SAN”来迭代它并分别创建它们各自的列:

Common Name      SANS            Common Name      SANS             => iterate
www.column.com   example1.com    www.column2.com  www.example1.com
                 example2.com                     www.example2.com
                 example3.com                     www.example3.com
                 example4.com                     www.example4.com  

到目前为止我能做到的事情:

jq -r '.enrollments[].csr | {cn: .cn, sans: .sans[]}  | [.cn, .sans] |@csv' certs.json > test.csv

它给了我以下输出:

"www.column.com","example1.com"
"www.column.com","example2.com"
"www.column.com","example3.com"
"www.column.com","example4.com"
"www.column2.com","www.example1.com"
"www.column2.com","www.example2.com"
"www.column2.com","www.example3.com"
"www.column2.com","www.example4.com"
...iterate through all records of the same type of data that occurs

所以,我能够将“cn”对象链接到“sans”数组。

如果我上面列出的所需格式不可行,以下输出是否有效?

Common Name      SANS
www.column.com   example1.com
www.column.com   example2.com
www.column.com   example3.com
www.column.com   example4.com
www.column2.com  www.example1.com
www.column2.com  www.example2.com
www.column2.com  www.example3.com
www.column2.com  www.example4.com
...iterate through all records of the same type of data that occurs

当我在网上研究时,我发现了一些其他人正在使用的技术,但我还没有找到解决方案。

对于列名,我一直在命令中使用它。但是,我尝试合并的所有内容似乎都不起作用:

(["Common Name"] + ["SANS"]),

此外,很多帖子都说要使用地图功能。

jq --raw-output '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv'

我得到以下输出:

jq: error (at <stdin>:51): object ({"adminCont...) is not valid in a csv row
0,1

exit status 5

看起来它卡在第一个对象上,我不确定“{”是否是编程出错的原因,但我随后尝试了以下操作。我试图用不同的路径替换“^”所在的区域,希望程序能找到我要找的东西:

jq --raw-output '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | 
                      ^                                    ^                            ^
$cols, $rows[] | @csv'

我尝试替换它的路径分别如下:

.enrollments[].csr
.csr.cn
.csr.sans

此时我不确定并决定与社区联系。同样,我是 jq 的新手,我正在尝试在这里找到联系、关系并学习逻辑。我愿意接受任何建议、意见和/或是否有更好的方法来获取这些信息。我也对使用其他格式输出的其他方法或最佳实践持开放态度。

如果已经存在类似的帖子,我提前道歉,因为我无法在搜索中找到它。如果是这样,请告诉我,我将按照社区准则编辑或删除此帖子。

非常感谢您的帮助。谢谢!

【问题讨论】:

  • 如果真正的目标是审计和编辑 JSON,使用 jq 来执行审计和编辑不是更好吗?

标签: json csv multiple-columns jq


【解决方案1】:

请求的格式在某些方面有点奇怪,所以让我们从一个更简单、或许更有用的目标开始——生成更常规的格式:

www.column.com  example1.com    www.column2.com www.example1.com
www.column.com  example2.com    www.column2.com www.example2.com
www.column.com  example3.com    www.column2.com www.example3.com
www.column.com  example4.com    www.column2.com www.example4.com

这可以使用过滤器来完成:

[ [.enrollments[0].csr |  {cn, sans: .sans[]} | [.cn, .sans] ],
  [.enrollments[1].csr |  {cn, sans: .sans[]} | [.cn, .sans] ] ]
| transpose
| map(add)
| .[]
| @csv

除第一行之外的所有内容中的第一列和第三列

现在通过调整上面的 jq 程序很容易获得请求的格式,使其变为:

[ [.enrollments[0].csr |  {cn, sans: .sans[]} | [.cn, .sans] ],
  [.enrollments[1].csr |  {cn, sans: .sans[]} | [.cn, .sans] ] ]
| transpose
| map(add)
| (.[0],
   (.[1:][] | (.[2] = "" | .[0] = "" )))
| @csv

通用方法

上面的第一个程序可以概括为允许“enrollments”数组任意长,如下所示:

[ .enrollments[]
  | [ .csr |  {cn, sans: .sans[]} | [.cn, .sans] ]]
| transpose
| map(add)
| .[]
| @tsv

这也可以像以前一样进行修改,以清除除第一行之外的所有值。

【讨论】:

  • 这太棒了。真正的快速问题,如果注册数组中有多个对象怎么办?我必须手动给它们编号吗?即 .enrollments[1...50].csr 等。顺便说一句,如果请求的格式有点奇怪,您会推荐更合乎逻辑的格式吗?
  • 关于数组,请看更新。关于奇怪的格式,我不明白真正的问题,所以在这一点上我没有什么要补充的。
  • 你好@peak。很抱歉造成混乱,你提到我关于我所询问的所需格式的问题很奇怪,所以我想问你是否有更好的方法来检索我试图抓住的阵型。我已经按照您的说明更新了问题。我想知道是否还有其他相同类型的数据出现,有没有办法收集它们。当前,在使用您的命令时,它会抓取所有 cn 和 sans 并将它们放入仅出现 [0] 和 [1] 的两列中。我以为使用 .[0] 会抓住一切,但它没有用。
猜你喜欢
  • 1970-01-01
  • 2013-12-09
  • 2020-01-29
  • 1970-01-01
  • 2017-09-18
  • 2021-07-23
  • 2021-12-22
  • 2022-10-07
  • 2023-01-24
相关资源
最近更新 更多