使用jq将JSON输出转换为CSV复杂结构

gcxthw6b  于 2023-11-14  发布在  其他
关注(0)|答案(3)|浏览(137)

我有一个现有的json文件,我需要转换,但我有它的麻烦。
下面是一个结构的例子:

jq -r '.document.results.summary.run.[] | [.run_number, .cinfo] ' input.json

[
  "42",
  [
    {
      "name": "Joe shmo",
      "state": "AZ",
      "city": "Phoenix"
    },
    {
      "name": "Jane shmo",
      "state": "CA",
      "city": "Blythe"
  ]
]
[
  "84",
  [
    {
      "name": "Jake shmo",
      "state": "NY",
      "city": "Albany"
    },
    {
      "name": "Jay shmo",
      "state": "TN",
      "city": "Franklin"
  ]
]

I need to convert this to a CSV to look like: 
"run_number","cinfo.name","cinfo.state","cinfo.city"

Example: 
"42","Joe shmo","AZ","Phoenix"
"42","Jane shmo","CA","Blythe"
"84","Jake shmo","NY","Albany"
"84","Jay shmo","TN","Franklin"

字符串
我试着用|@csv我得到:
jq: error (at input.json:1397): array ([{"@name":"...) is not valid in a csv row我相信这是因为它是一个多个索引的数组。我如何使用jq转换输出?

vcirk6k6

vcirk6k61#

你尝试将@csv应用于一个包含非字符串的数组。你必须分解它们才能得到值。

jq -r '
  .document.results.summary.run.[] | . as {$run_number}
  | .cinfo[] | [$run_number, .name, .state, .city]
  | @csv
' input.json

字符串
如果一切顺利(如果您提供了input.json,我可以测试它),这应该会产生

"42","Joe shmo","AZ","Phoenix"
"42","Jane shmo","CA","Blythe"
"84","Jake shmo","NY","Albany"
"84","Jay shmo","TN","Franklin"

5t7ly7z5

5t7ly7z52#

你的代码示例中没有有效的JSON文件。也许你想这样写:

[
  [
    "42",
    [
      {
        "name": "Joe shmo",
        "state": "AZ",
        "city": "Phoenix"
      },
      {
        "name": "Jane shmo",
        "state": "CA",
        "city": "Blythe"
      }
    ]
  ],
  [
    "84",
    [
      {
        "name": "Jake shmo",
        "state": "NY",
        "city": "Albany"
      },
      {
        "name": "Jay shmo",
        "state": "TN",
        "city": "Franklin"
      }
    ]
  ]
]

字符串
在这种情况下,您可以使用以下命令:

jq -r '.[] | .[0] as $run_number | .[1][] | [$run_number, .name, .state, .city] | @csv' input.json


你会得到这样的结果:

"42","Joe shmo","AZ","Phoenix"
"42","Jane shmo","CA","Blythe"
"84","Jake shmo","NY","Albany"
"84","Jay shmo","TN","Franklin"

bd1hkmkf

bd1hkmkf3#

另一种方法是将以下内容标记到已有的jq过滤器(demo)的末尾:

| [ .[0] ] + (.[1] [] | [ .[] ]) | @csv

字符串
完整的过滤器应该是:

.document.results.summary.run.[] 
| [.run_number, .cinfo] 
| [ .[0] ] + (.[1] [] | [ .[] ])
| @csv


为了理解它是如何工作的,让我们分解它,看看[.run_number, .cinfo]生成的第一行会发生什么:

  • .[1] []将首先解压缩info数组,这样它将产生两个对象,即,
{"name":"Joe shmo","state":"AZ","city":"Phoenix"}
{"name":"Jane shmo","state":"CA","city":"Blythe"}

  • 这两个对象通过管道传输到[ .[] ],这将把它们转换为数组,如下所示:
["Joe shmo","AZ","Phoenix"]
["Jane shmo","CA","Blythe"]

  • 现在,当您将其添加到[ .[0] ](即[ "42" ])时,jq将对流中的两个数组执行数组concat,导致:
["42","Joe shmo","AZ","Phoenix"]
["42","Jane shmo","CA","Blythe"]

  • 这将被传递到@csv过滤器,生成我们需要的行。

对另一个run也重复整个过程,我们得到了所需的输出。

相关问题