我已经成功地弄清了如何取消jq中对象的嵌套;但是,我编写的工作代码需要大量重复。我觉得可能有一种更简洁或更简洁的方法来实现相同的结果,我想知道它是什么。
使用以下嵌套的公司结构,假设目标是为列出的每个人提取名称,ID,公司和站点。 (我们可以忽略该地址。)
{
"company": "Initrode",
"sites": [
{
"name": "HQ",
"address": "123 Main Street",
"personnel": [
{
"name": "John Smith",
"UID": 12345
},
{
"name": "Jane Doe",
"UID": 23456
}
]
},
{
"name": "Branch Office",
"address": "Spodunk, Nowhereville",
"personnel": [
{
"name": "Fred Anderson",
"UID": 56789
},
{
"name": "Bill Jones",
"UID": 34567
}
]
}
]
}
{
"company": "Inittech",
"sites": [
{
"name": "Main Office",
"address": "5678 Avenue Blvd",
"personnel": [
{
"name": "Fred Johnson",
"UID": 6543
},
{
"name": "James Fredson",
"UID": 9876
}
]
},
{
"name": "Testing Station",
"address": "Alaskan Wilderness",
"personnel": [
{
"name": "Sally May",
"UID": 5432
},
{
"name": "Jack James",
"UID": 8765
}
]
}
]
}
jq '{company,site: .sites[]}|
{company,site: .site.name,personnel: .site.personnel[]}|
{name: .personnel.name,id: .personnel.UID,company,site}' sample.json
{
"name": "John Smith",
"id": 12345,
"company": "Initrode",
"site": "HQ"
}
{
"name": "Jane Doe",
"id": 23456,
"company": "Initrode",
"site": "HQ"
}
{
"name": "Fred Anderson",
"id": 56789,
"company": "Initrode",
"site": "Branch Office"
}
{
"name": "Bill Jones",
"id": 34567,
"company": "Initrode",
"site": "Branch Office"
}
{
"name": "Fred Johnson",
"id": 6543,
"company": "Inittech",
"site": "Main Office"
}
{
"name": "James Fredson",
"id": 9876,
"company": "Inittech",
"site": "Main Office"
}
{
"name": "Sally May",
"id": 5432,
"company": "Inittech",
"site": "Testing Station"
}
{
"name": "Jack James",
"id": 8765,
"company": "Inittech",
"site": "Testing Station"
}
这里涉及很多重复。除了在流水线的每个阶段重复外部标签之外,在流水线的第二部分和第三部分还分别重复了.site
和.personnel
。
我的真实数据要复杂得多,所以这种重复甚至更糟,更难阅读。
顺便说一下,下面是我为实现上述相同目标而尝试的一些非工作代码:
jq '{company,site: .sites[].name,name: .sites[].personnel[].name,id: .sites[].personnel[].UID}' sample.json
重复的次数要少得多,但是不幸的是,它返回与公司每个ID和站点相关联的每个人-错误的结果,例如数据库“交叉连接”而不是“内部连接”。
我不太了解如何用文字描述此处需要的内容,但希望上面的示例可以帮助您弄清楚。
一种描述它的方法是,我试图将子对象数组中的多个名称/值对合并到顶级对象中,而不将来自的名称/值对的任何组合一起返回相同数组值内的子对象。但是,即使对于我来说,这也不是一件容易的事。因此,上面的示例输入/输出。
仅出于兴趣,这是我拥有的真实工作代码,属性名称被混淆了:
jq '.pears[]|{pear: .name,file: .somepath,toBeFiltered: (.appletypes[]|select(.name == "orange")|.bananas[]|{banana: .name,apples: .apples[]})}|{pear,file,banana: .toBeFiltered.banana,applestem: .toBeFiltered.apples.applestem,orangecomment: (.toBeFiltered.apples.peaches[]|select(.akey == "string")|.avalue.value),linenumber: (.toBeFiltered.apples.peaches[]|select(.akey == "string")|.line)}' realfile.json
答案 0 :(得分:1)
也许您缺少的是jq变量的实用程序:
.company as $company
| .sites[]
| .name as $site
| .personnel[]
| { name, id: .UID, company: $company, site: $site }
但是,也可以通过使用括号来避免变量。如果您不介意按键的顺序略有不同,则可以这样写:
(.sites[] | ( (.personnel[] | { name, id: .UID} ) + {site: .name} )) + {company}
如果键必须按照Q中显示的顺序,则只需将以下过滤器附加到上述管道中即可:
{name, id, company, site}