如何 select 和 jq 合并对象数据?
How to select and merge objects data with jq?
玩了 jq 几个小时后,我需要你的帮助来select创建和合并对象。
我有这种 JSON :
{
"cluster-1": {
"vhosts": {
"vhost_aaa": {
"postgresql": {
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}
}
}
},
"cluster-2": {
"vhosts": {
"vhost_bbb": {
"postgresql": {
"bdd1": {
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
}
}
}
},
"vhost_ccc": {
"postgresql": {
"bdd1": {
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
}
}
}
}
}
}
这是一个很深的 JSON 它告诉我,在 cluster-x 上有 vhosts (vhosts_xxx) 可能使用一种由服务器托管的数据库(此处 postgresql)(此处 bdd1 或 bdd2 ) 其中包含数据库 (db_xxx),我想在其中创建指定的用户 (user_xxx)凭据详细信息。哎哟!
我的目标是 select 部分数据来执行特定操作,因此对于数据库服务器,我希望所有操作都在同一台服务器上执行,所以这就是我尝试使用 jq 生成的内容:
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
},
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
},
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
有了这个过滤器 (..|.vhosts?|..|.postgresql?)|objects
,我可以隔离我需要的数据。
{
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}
{
"bdd1": {
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
}
}
}
{
"bdd1": {
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
}
}
下一步是合并按 bddx 分组的所有这些数据。
欢迎任何帮助或建议:)
您可以使用 to_entries
将对象转换为 key/value 对 properties/values 的数组。然后您可以将这些对分组以构建您的结果。
[..|.vhosts?|..|.postgresql?|objects|to_entries[]]
| reduce group_by(.key)[] as $g ({};
.[$g[0].key] = [$g[].value]
)
这会产生以下结果:
{
"bdd1": [
{
"db_aaa": {
"user_aaa": { "password": "xxx" }
}
},
{
"db_ccc": {
"user_ccc": { "password": "xxx" }
}
},
{
"db_bbb": {
"user_bbb": { "password": "xxx" },
"user_bbb_ro": { "password": "xxx" }
}
}
],
"bdd2": [
{
"db_aaa": {
"user_aaa": { "password": "xxx" }
}
}
]
}
避免使用 ..
可能更安全(即更稳健)。如果数据的结构如您所指出的,那么以下过滤器将适合执行您任务的 "select" 部分:
to_entries[] | .value.vhosts
| to_entries[] | .value.postgresql // empty
然后您可以按照 Jeff 建议的方式使用它:
[to_entries[] | .value.vhosts
| to_entries[] | .value.postgresql // empty
| to_entries[]]
| group_by(.key)
| reduce .[] as $g ({}; .[$g[0].key] = [$g[].value] )
这是另一个解决方案 reduces Sylvain's filter using * object multiplication
reduce ((..|.vhosts?|..|.postgresql?)|objects) as $i({}; . *= $i)
使用它生成的示例数据
{
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
},
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
},
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}
玩了 jq 几个小时后,我需要你的帮助来select创建和合并对象。
我有这种 JSON :
{
"cluster-1": {
"vhosts": {
"vhost_aaa": {
"postgresql": {
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}
}
}
},
"cluster-2": {
"vhosts": {
"vhost_bbb": {
"postgresql": {
"bdd1": {
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
}
}
}
},
"vhost_ccc": {
"postgresql": {
"bdd1": {
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
}
}
}
}
}
}
这是一个很深的 JSON 它告诉我,在 cluster-x 上有 vhosts (vhosts_xxx) 可能使用一种由服务器托管的数据库(此处 postgresql)(此处 bdd1 或 bdd2 ) 其中包含数据库 (db_xxx),我想在其中创建指定的用户 (user_xxx)凭据详细信息。哎哟!
我的目标是 select 部分数据来执行特定操作,因此对于数据库服务器,我希望所有操作都在同一台服务器上执行,所以这就是我尝试使用 jq 生成的内容:
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
},
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
},
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
有了这个过滤器 (..|.vhosts?|..|.postgresql?)|objects
,我可以隔离我需要的数据。
{
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}
{
"bdd1": {
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
}
}
}
{
"bdd1": {
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
}
}
下一步是合并按 bddx 分组的所有这些数据。 欢迎任何帮助或建议:)
您可以使用 to_entries
将对象转换为 key/value 对 properties/values 的数组。然后您可以将这些对分组以构建您的结果。
[..|.vhosts?|..|.postgresql?|objects|to_entries[]]
| reduce group_by(.key)[] as $g ({};
.[$g[0].key] = [$g[].value]
)
这会产生以下结果:
{
"bdd1": [
{
"db_aaa": {
"user_aaa": { "password": "xxx" }
}
},
{
"db_ccc": {
"user_ccc": { "password": "xxx" }
}
},
{
"db_bbb": {
"user_bbb": { "password": "xxx" },
"user_bbb_ro": { "password": "xxx" }
}
}
],
"bdd2": [
{
"db_aaa": {
"user_aaa": { "password": "xxx" }
}
}
]
}
避免使用 ..
可能更安全(即更稳健)。如果数据的结构如您所指出的,那么以下过滤器将适合执行您任务的 "select" 部分:
to_entries[] | .value.vhosts
| to_entries[] | .value.postgresql // empty
然后您可以按照 Jeff 建议的方式使用它:
[to_entries[] | .value.vhosts
| to_entries[] | .value.postgresql // empty
| to_entries[]]
| group_by(.key)
| reduce .[] as $g ({}; .[$g[0].key] = [$g[].value] )
这是另一个解决方案 reduces Sylvain's filter using * object multiplication
reduce ((..|.vhosts?|..|.postgresql?)|objects) as $i({}; . *= $i)
使用它生成的示例数据
{
"bdd1": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
},
"db_bbb": {
"user_bbb": {
"password": "xxx"
},
"user_bbb_ro": {
"password": "xxx"
}
},
"db_ccc": {
"user_ccc": {
"password": "xxx"
}
}
},
"bdd2": {
"db_aaa": {
"user_aaa": {
"password": "xxx"
}
}
}
}