如何编写 jq 查询以将 JSON 文件转换为 CSV?

How do I write a jq query to convert a JSON file to CSV?

JSON 个文件如下所示:

{
  "name": "My Collection",
  "description": "This is a great collection.",
  "date": 1639717379161,
  "attributes": [
    {
      "trait_type": "Background",
      "value": "Sand"
    },
    {
      "trait_type": "Skin",
      "value": "Dark Brown"
    },
    {
      "trait_type": "Mouth",
      "value": "Smile Basic"
    },
    {
      "trait_type": "Eyes",
      "value": "Confused"
    }
  ]  
}

我发现 a shell script 使用 jq 并具有以下代码:

i=1
for eachFile in *.json; do
    cat $i.json | jq -r '.[] | {column1: .name, column2: .description} | [.[] | tostring] | @csv' > extract-$i.csv
    echo "converted $i of many json files..."
    ((i=i+1))
done

但它的输出是:

jq: error (at <stdin>:34): Cannot index string with string "name"
converted 1 of many json files...

关于如何完成这项工作有什么建议吗?谢谢!

快速jq课
===========

jq 过滤器应用如下:
jq -r '.name_of_json_field_0 <optional filter>, .name_of_json_field_1 <optional filter>'
等等等等。单点是最简单的过滤器;它使数据字段保持不变。

jq -r '.name_of_field .'

您也可以保持过滤器字段不变以获得相同的效果。 在你的情况下: jq -r '.name, .description' 将提取这两个字段的值。

.[] 将展开一个数组,以便将下一个管道过滤器应用于每个展开的值。示例:
jq -r '.attributes | .[]
提取所有 trait_types 个对象。

您有时可能希望通过将过滤器括在方括号中来重新打包数组中的对象:
jq -r '[.name, .description, .date]

您有时可能希望通过将过滤器括在花括号中来重新打包对象中的数据:
`jq -r '{new_field_name: .name, super_new_field_name: .description}'

玩弄这些,我得到了

jq -r '[.name, .description, .date, (.attributes | [.[] | .trait_type] | @csv | gsub(",";";") | gsub("\"";"")), (.attributes | [.[] | .value] | .[]] | @csv | gsub(",";";") | gsub("\"";""))] | @csv'

给我们:
"My Collection","This is a great collection.",1639717379161,"Background;Skin;Mouth;Eyes","Sand;Dark Brown;Smile Basic;Confused"

名称、描述和日期保持原样,所以让我们一步步分解奇怪的部分。

.attributes | [.[] | .trait_type]
.[] 提取属性数组的每个元素并将其结果通过管道传输到下一个过滤器,它表示简单地提取 trait_type,在那里它们被重新打包到一个数组中。

.attributes | [.[] | .trait_type] | @csv
将数组转换为可解析的 csv 格式。

(.attributes | [.[] | .trait_type] | @csv | gsub(",";";") | gsub("\"";""))
显然,Parens 将此与其他评估分开。 这里的第一个 gsub 将逗号替换为分号,因此它们不会被解释为单独的字段,第二个删除所有额外的双引号。