简体   繁体   English

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

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

The JSON files look like: 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"
    }
  ]  
}

I found a shell script that uses jq and has this code:我发现了一个使用jq并具有以下代码的 shell 脚本

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

But its output is:但它的 output 是:

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

Any suggestions on how I can make this work?关于如何完成这项工作的任何建议? Thank you!谢谢!

Quick jq lesson快速jq课
=========== ===========

jq filters are applied like this: jq 过滤器的应用如下:
jq -r '.name_of_json_field_0 <optional filter>, .name_of_json_field_1 <optional filter>'
and so on and so forth.等等等等。 A single dot is the simplest filter;单点是最简单的过滤器; it leaves the data field untouched.它使数据字段保持不变。

jq -r '.name_of_field.'

You may also leave the filter field untouched for the same effect.您也可以保持过滤器字段不变以获得相同的效果。 In your case: jq -r '.name, .description' will extract the values of both those fields.在您的情况下: jq -r '.name, .description'将提取这两个字段的值。

.[] will unwrap an array to have the next piped filter applied to each unwrapped value. .[]将展开一个数组以将下一个管道过滤器应用于每个展开的值。 Example:例子:
jq -r '.attributes |.[]
extracts all trait_types objects.提取所有 trait_types 对象。

You may sometime want to repackage objects in an array by surrounding the filter in brackets:您有时可能希望通过将过滤器括在括号中来重新打包数组中的对象:
jq -r '[.name, .description, .date]

You may sometime want to repackage data in an object by surrounding the filter in curly braces:您有时可能希望通过将过滤器括在花括号中来重新打包 object 中的数据:
`jq -r '{new_field_name: .name, super_new_field_name: .description}' `jq -r '{new_field_name: .name, super_new_field_name: .description}'

playing around with these, I was able to get玩弄这些,我能够得到

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

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

Name and description were left as is, so let's break down the weird parts, one step at a time.名称和描述保持原样,所以让我们一步一步分解奇怪的部分。

.attributes | [.[] |.trait_type]
.[] extracts each element of the attributes array and pipes the result of that into the next filter, which says to simply extract trait_type . .[]提取属性数组的每个元素并将其结果通过管道传递到下一个过滤器,即简单地提取trait_type

.attributes | [.[] |.trait_type] | @csv
turn the array into a csv-parsable format.将数组转换为 csv 可解析格式。

(.attributes | [.[] |.trait_type] | @csv | gsub(",";";") | gsub("\"";""))
Parens separate this from the rest of the evaluations, obviously. Parens 显然将其与评估的 rest 分开。 The first gsub here replaces commas with semicolons so they don't get interpreted as a separate field, the second removes all extra double quotes.这里的第一个gsub用分号替换逗号,因此它们不会被解释为单独的字段,第二个删除所有额外的双引号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM