You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于相同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

关键修正点

  1. 批量获取权限:直接通过jq '.values'获取所有组权限数组,不需要逐个循环处理组,避免重复的JQ操作和赋值错误。
  2. 直接构建项目对象:在添加项目到Projects数组时,直接把组权限数组赋值给Groups字段,一步到位,无需后续更新。
  3. 变量引用优化:使用--argjson传递JSON数组,避免字符串转义问题,确保权限结构正确。

这样处理后,每个项目的Groups数组会直接包含所有对应的权限对象,完全符合你期望的结果。


内容的提问来源于Stack Exchange,提问作者Franz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 19:35:16