基于数组中的元素,使用 jq 从 json 创建 CSV
Creating a CSV from json using jq, based on elements in array
我有以下 json 格式需要转换为 CSV
[{
"name": "joe",
"age": 21,
"skills": [{
"lang": "spanish",
"grade": "47",
"school": {
"name": "my school",
"url": "example.com/sp-school"
}
}, {
"lang": "english",
"grade": "87"
}]
},
{
"name": "sarah",
"age": 34,
"skills": [{
"lang": "french",
"grade": "47",
"school": {
"name": "my school",
"url": "example.com/sp-school"
}
}, {
"lang": "english",
"grade": "87"
}]
}, {
"name": "jim",
"age": 26,
"skills": [{
"lang": "spanish",
"grade": "60"
}, {
"lang": "english",
"grade": "66",
"school": {
"name": "eg school",
"url": "eg-school.com"
}
}]
}
]
转换为 csv
name,age,grade,school,url,file,line_number
joe,21,47,"my school","example.com/sp-school",sample.json,1
jim,26,60,"","",sample.json,3
因此,如果 lang=spanish,则添加顶级字段和 skills 数组中的对象,如果存在,则添加 skills 对象中的 school hash for spanish
我还想添加它来自的文件和行号。
我想使用 jq 来完成这项工作,但无法弄清楚语法,有人帮我吗?
你的数据在input.json,下面的jq程序在tocsv.jq:
.[]
| [.name, .age] +
(.skills[]
| select(.lang == "spanish")
| [.grade, .school.name, .school.url, input_filename, input_line_number] )
| @csv
调用:
jq -r -f tocsv.jq input.json
产量:
"joe",21,"47","my school","example.com/sp-school","input.json",51
"jim",26,"60",,,"input.json",51
如果要将 number-valued 字符串转换为数字,可以使用 "tonumber" 过滤器。如果您希望 null-valued 字段替换为字符串,请使用例如.school.name // ""
当然,这种方法不会产生非常有用的行号。一种会产生更高粒度的方法是将单个对象流式传输到 jq 中,但这样您会丢失文件名。要恢复文件名,您可以将其作为参数传递。所以你会有一个像这样的管道:
jq -c '.[]' input.json | jq -r --arg file input.json -f tocsv2.jq
其中 tocsv2.jq 类似于上面的 tscsv.jq,但没有初始 .[] |
,并且使用 $file
而不是 input_filename
。
最后,请考虑使用 TSV 格式 (@tsv) 而不是相当混乱的 CSV 格式 (@csv)。
我有以下 json 格式需要转换为 CSV
[{
"name": "joe",
"age": 21,
"skills": [{
"lang": "spanish",
"grade": "47",
"school": {
"name": "my school",
"url": "example.com/sp-school"
}
}, {
"lang": "english",
"grade": "87"
}]
},
{
"name": "sarah",
"age": 34,
"skills": [{
"lang": "french",
"grade": "47",
"school": {
"name": "my school",
"url": "example.com/sp-school"
}
}, {
"lang": "english",
"grade": "87"
}]
}, {
"name": "jim",
"age": 26,
"skills": [{
"lang": "spanish",
"grade": "60"
}, {
"lang": "english",
"grade": "66",
"school": {
"name": "eg school",
"url": "eg-school.com"
}
}]
}
]
转换为 csv
name,age,grade,school,url,file,line_number
joe,21,47,"my school","example.com/sp-school",sample.json,1
jim,26,60,"","",sample.json,3
因此,如果 lang=spanish,则添加顶级字段和 skills 数组中的对象,如果存在,则添加 skills 对象中的 school hash for spanish
我还想添加它来自的文件和行号。
我想使用 jq 来完成这项工作,但无法弄清楚语法,有人帮我吗?
你的数据在input.json,下面的jq程序在tocsv.jq:
.[]
| [.name, .age] +
(.skills[]
| select(.lang == "spanish")
| [.grade, .school.name, .school.url, input_filename, input_line_number] )
| @csv
调用:
jq -r -f tocsv.jq input.json
产量:
"joe",21,"47","my school","example.com/sp-school","input.json",51
"jim",26,"60",,,"input.json",51
如果要将 number-valued 字符串转换为数字,可以使用 "tonumber" 过滤器。如果您希望 null-valued 字段替换为字符串,请使用例如.school.name // ""
当然,这种方法不会产生非常有用的行号。一种会产生更高粒度的方法是将单个对象流式传输到 jq 中,但这样您会丢失文件名。要恢复文件名,您可以将其作为参数传递。所以你会有一个像这样的管道:
jq -c '.[]' input.json | jq -r --arg file input.json -f tocsv2.jq
其中 tocsv2.jq 类似于上面的 tscsv.jq,但没有初始 .[] |
,并且使用 $file
而不是 input_filename
。
最后,请考虑使用 TSV 格式 (@tsv) 而不是相当混乱的 CSV 格式 (@csv)。