![使用 jq 从面向列的 JSON 中提取值并采用 CSV 格式](https://linux22.com/image/13581/%E4%BD%BF%E7%94%A8%20jq%20%E4%BB%8E%E9%9D%A2%E5%90%91%E5%88%97%E7%9A%84%20JSON%20%E4%B8%AD%E6%8F%90%E5%8F%96%E5%80%BC%E5%B9%B6%E9%87%87%E7%94%A8%20CSV%20%E6%A0%BC%E5%BC%8F.png)
我有以下 JSON 文件,其中数据存储为rank
数组中枚举的列:
{
"data": [
{
"displayName": "First Name",
"rank": 1,
"value": "VALUE"
},
{
"displayName": "Last Name",
"rank": 2,
"value": "VALUE"
},
{
"displayName": "Position",
"rank": 3,
"value": "VALUE"
},
{
"displayName": "Company Name",
"rank": 4,
"value": "VALUE"
},
{
"displayName": "Country",
"rank": 5,
"value": "VALUE"
}
]
}
我想要一个这种格式的 CSV 文件,其中标题来自列的值displayName
,列中的数据是单数value
键的值:
First Name, Last Name, Position, Company Name, Country
VALUE, VALUE, VALUE, VALUE, VALUE
仅使用这可能吗jq
?我没有任何编程技能。
答案1
jq 有一个过滤器 @csv,用于将数组转换为 CSV 字符串。此过滤器考虑了与 CSV 格式相关的大部分复杂性,从字段中嵌入的逗号开始。 (jq 1.5 有一个类似的过滤器 @tsv,用于生成制表符分隔值文件。)
当然,如果标题和值都保证没有逗号和双引号,那么可能不需要使用@csv过滤器。否则,使用它可能会更好。
例如,如果“公司名称”为“Smith, Smith and Smith”,并且其他值如下所示,则使用“-r”选项调用 jq 将生成有效的 CSV:
$ jq -r '.data | map(.displayName), map(.value) | @csv' so.json2csv.json
"First Name","Last Name","Position","Company Name","Country"
"John (""Johnnie"")","Doe","Director, Planning and Posterity","Smith, Smith and Smith","Transylvania"
答案2
我更喜欢将每条记录放在 CSV 中的一行中。
jq -r '.data | map([.displayName, .rank, .value] | join(", ")) | join("\n")'
给定问题中的数据,输出
First Name, 1, VALUE
Last Name, 2, VALUE
Position, 3, VALUE
Company Name, 4, VALUE
Country, 5, VALUE
答案3
仅给出这个文件,您可以执行以下操作:
<testfile jq -r '.data | map(.displayName), map(.value) | join(", ")'
操作.
员从对象/散列中选择一个字段。因此,我们从 开始.data
,它返回其中包含数据的数组。然后,我们对数组进行两次映射,首先选择 displayName,然后选择值,得到两个仅包含这些键的值的数组。对于每个数组,我们用“,”将元素连接起来形成两行。该-r
参数告诉jq
不要引用结果字符串。
如果您的实际文件较长(即包含多个人的条目),您可能需要更复杂的东西。
答案4
由于您标记了此文件python
并假设文件名json
是x.json
import os, json
with open('x.json') as f:
x = json.load(f)
print '{}{}{}'.format(', '.join(y['displayName'] for y in x['data']), os.linesep,
', '.join(y['value'] for y in x['data']))
First Name, Last Name, Position, Company Name, Country
VALUE, VALUE, VALUE, VALUE, VALUE