如何 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)(此处 bdd1bdd2 ) 其中包含数据库 (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"
      }
    }
  }
}