基于相同KEY使用JQ合并对象至数组的Bitbucket权限处理问题
问题背景
我正在编写Bash脚本,从Bitbucket API获取项目及权限信息,需要构建包含所有项目及其对应权限的JSON结构。
基础JSON结构
{ "Projects": [ { "Project": [ { "KEY": "FOO", "Name": "A new Bitbucket project", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY1", "Name": "Name1", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY2", "Name": "Name2", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY3", "Name": "Name3", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY4", "Name": "Name4", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY5", "Name": "Name5", "Permissions": [ { "Groups": [], "Users": [] } ] } ] } ] }
循环生成的权限对象
{ "Project": [ { "KEY": "FOO", "Name": "A new Bitbucket project", "Permissions": [ { "Groups": [], "Users": [] } ] }, { "Permissions": [ { "group": { "name": "test-group-4" }, "permission": "PROJECT_READ" } ] } ] } { "Project": [ { "KEY": "KEY2", "Name": "Name2", "Permissions": [ { "Groups": [], "Users": [] } ] }, { "Permissions": [ { "group": { "name": "test-group-1" }, "permission": "PROJECT_WRITE" } ] } ] } { "Project": [ { "KEY": "KEY5", "Name": "Name5", "Permissions": [ { "Groups": [], "Users": [] } ] }, { "Permissions": [ { "group": { "name": "test-group-1" }, "permission": "PROJECT_READ" } ] } ] } { "Project": [ { "KEY": "KEY5", "Name": "Name5", "Permissions": [ { "Groups": [], "Users": [] } ] }, { "Permissions": [ { "group": { "name": "test-group-2" }, "permission": "PROJECT_WRITE" } ] } ] } { "Project": [ { "KEY": "KEY5", "Name": "Name5", "Permissions": [ { "Groups": [], "Users": [] } ] }, { "Permissions": [ { "group": { "name": "test-group-3" }, "permission": "PROJECT_ADMIN" } ] } ] }
当前Bash脚本
#!/bin/bash set -e while getopts u:p:b: flag; do case "${flag}" in u) username=${OPTARG} ;; p) password=${OPTARG} ;; b) url=${OPTARG} ;; esac done keys=$(curl -s -u $username:$password -X GET -H "Content-Type: application/json" $url/rest/api/1.0/projects/ | jq -r .values[].key) projects="{\"Projects\" : []}" for key in $keys; do groups=$(curl -s -u $username:$password -X GET -H "Content-Type: application/json" $url/rest/api/1.0/projects/$key/permissions/groups/ | jq) project_name=$(curl -s -u $username:$password -X GET -H "Content-Type: application/json" $url/rest/api/1.0/projects/$key | jq -r .name) group_names=$(echo ${groups} | jq -r .values[].group.name) group_permissions=$(echo ${groups} | jq -r .values[].permission) projects=$(echo "$projects" | jq ".Projects[.Projects| length] |={Project:[{KEY:\"$key\",Name:\"$project_name\",Permissions:[{Groups:[],Users:[]}]}]}") for group in $group_names; do data=$(echo ${groups} | jq -r --arg GROUP "$group" '.values[] | select(.group.name==$GROUP)') updated_project=$(echo "$projects" | jq ".Projects[] | select(.Project[].KEY==\"$key\") | .Project[].Permissions[.Permissions | length].Groups[.Groups | length] |= $data") projects=$(echo "$projects" | jq "(.Projects[] | select(.Project[].KEY==\"$key\") | . ) |= $updated_project") done done echo $projects | jq
期望的合并结果
{ "Projects": [ { "Project": [ { "KEY": "FOO", "Name": "A new Bitbucket project", "Permissions": [ { "Groups": [ { "group": { "name": "test-group-4" }, "permission": "PROJECT_READ" } ], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY1", "Name": "Name1", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY2", "Name": "Name2", "Permissions": [ { "Groups": [ { "group": { "name": "test-group-1" }, "permission": "PROJECT_WRITE" } ], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY3", "Name": "Name3", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY4", "Name": "Name4", "Permissions": [ { "Groups": [], "Users": [] } ] } ] }, { "Project": [ { "KEY": "KEY5", "Name": "Name5", "Permissions": [ { "Groups": [ { "group": { "name": "test-group-1" }, "permission": "PROJECT_READ" }, { "group": { "name": "test-group-2" }, "permission": "PROJECT_WRITE" }, { "group": { "name": "test-group-3" }, "permission": "PROJECT_ADMIN" } ], "Users": [] } ] } ] } ] }
当前遇到的问题
- 使用原有JQ操作时,仅会保留最后一个权限对象,无法追加所有权限;
- 修改JQ路径后,权限对象被添加为Project数组的新元素,而非追加到对应Project的Groups数组中。
请求提供正确的JQ操作方法,实现基于KEY将所有权限对象合并到对应Project的Groups数组中。
解决方案
你的核心问题在于循环中更新Groups数组时,JQ路径错误且重复赋值逻辑混乱。直接一次性获取所有组权限并批量追加,而非逐个循环处理,效率更高且逻辑更清晰。
修正后的Bash脚本:
#!/bin/bash set -e while getopts u:p:b: flag; do case "${flag}" in u) username=${OPTARG} ;; p) password=${OPTARG} ;; b) url=${OPTARG} ;; esac done # 初始化Projects结构 projects='{"Projects": []}' # 获取所有项目KEY keys=$(curl -s -u "$username:$password" -H "Content-Type: application/json" "$url/rest/api/1.0/projects/" | jq -r '.values[].key') for key in $keys; do # 获取项目名称 project_name=$(curl -s -u "$username:$password" -H "Content-Type: application/json" "$url/rest/api/1.0/projects/$key" | jq -r '.name') # 获取该项目的所有组权限,直接提取values数组 group_permissions=$(curl -s -u "$username:$password" -H "Content-Type: application/json" "$url/rest/api/1.0/projects/$key/permissions/groups/" | jq '.values') # 直接构建包含权限的项目对象并追加到Projects数组 projects=$(echo "$projects" | jq --arg key "$key" --arg name "$project_name" --argjson groups "$group_permissions" ' .Projects += [{ "Project": [{ "KEY": $key, "Name": $name, "Permissions": [{ "Groups": $groups, "Users": [] }] }] }] ') done # 输出格式化后的JSON echo "$projects" | jq
关键修正点
- 批量获取权限:直接通过
jq '.values'获取所有组权限数组,不需要逐个循环处理组,避免重复的JQ操作和赋值错误。 - 直接构建项目对象:在添加项目到Projects数组时,直接把组权限数组赋值给Groups字段,一步到位,无需后续更新。
- 变量引用优化:使用
--argjson传递JSON数组,避免字符串转义问题,确保权限结构正确。
这样处理后,每个项目的Groups数组会直接包含所有对应的权限对象,完全符合你期望的结果。
内容的提问来源于Stack Exchange,提问作者Franz
相关产品推荐
相关产品推荐

