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

Azure Pipeline中PowerShell传递数组至ARM模板时出现JToken类型不匹配错误求助

这个问题我之前也碰到过,核心原因很明确:你的ARM模板里fooBar参数定义的是object类型,但通过Pipeline传递时,实际传过去的是JSON字符串,ARM根本没法把字符串自动解析成它需要的对象类型,所以就报了那个类型不匹配的错误。

下面给你两种解决方案,优先推荐第一种,因为复杂对象用参数文件传递最靠谱:

方案一:用ARM参数文件传递复杂对象

这是处理复杂参数最稳妥的方式,咱们直接生成符合ARM规范的参数文件,而不是用变量传递:

1. 修改PowerShell脚本生成参数文件

把原来设置变量的代码改成生成参数文件的逻辑,这样脚本跑完后会输出一个ARM能直接识别的参数文件:

param( 
    [string][parameter(Mandatory = $true)] $keyVaultName, 
    [string][parameter(Mandatory = $true)] $resourceGroupName 
)

$keyVault = Get-AzKeyVault -Name $keyVaultName -ResourceGroupName $resourceGroupName
if ($null -ne $keyVault) {
    $keyVaultAccessPolicies = $keyVault.AccessPolicies
    $armAccessPolicies = @()
    
    if($keyVaultAccessPolicies) {
        foreach($keyVaultAccessPolicy in $keyVaultAccessPolicies) {
            $armAccessPolicy = [pscustomobject]@{ 
                tenantId = $keyVaultAccessPolicy.TenantId; 
                objectId = $keyVaultAccessPolicy.ObjectId 
            }
            $armAccessPolicyPermissions = [pscustomobject]@{ 
                keys = $keyVaultAccessPolicy.PermissionsToKeys; 
                secrets = $keyVaultAccessPolicy.PermissionsToSecrets; 
                certificates = $keyVaultAccessPolicy.PermissionsToCertificates; 
                storage = $keyVaultAccessPolicy.PermissionsToStorage 
            }
            $armAccessPolicy | Add-Member -MemberType NoteProperty -Name permissions -Value $armAccessPolicyPermissions
            $armAccessPolicies += $armAccessPolicy
        }
    }

    # 构建ARM参数文件的标准结构
    $parameterFileContent = [pscustomobject]@{
        "$schema" = "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"
        contentVersion = "1.0.0.0"
        parameters = [pscustomobject]@{
            name = [pscustomobject]@{ value = $keyVaultName }
            fooBar = [pscustomobject]@{ value = [pscustomobject]@{ list = $armAccessPolicies } }
        }
    }

    # 把参数文件保存到你的artifact目录里,路径根据你实际的结构调整
    $outputPath = "$(System.DefaultWorkingDirectory)/$(Provisioning.Package.Name)/Templates/key-vault-params.json"
    $parameterFileContent | ConvertTo-Json -Depth 5 | Out-File $outputPath -Force
}

2. 更新Pipeline的YAML配置

接下来修改部署任务,指定咱们生成的参数文件,要是还有其他需要覆盖的参数(比如name想用Pipeline变量),直接在overrideParameters里加就行:

- task: AzureResourceManagerTemplateDeployment@3
  displayName: 'Provision Key Vault'
  inputs:
    deploymentScope: 'Resource Group'
    azureResourceManagerConnection: ${{ parameters.azureSubscriptionName }}
    subscriptionId: ${{ parameters.azureSubscriptionId }}
    action: 'Create Or Update Resource Group'
    resourceGroupName: '$(Resource.Group.Name)'
    location: '$(Region)'
    templateLocation: 'Linked artifact'
    csmFile: '$(Provisioning.Package.Name)/Templates/key-vault-deploy.json'
    # 指定刚才生成的参数文件
    csmParametersFile: '$(Provisioning.Package.Name)/Templates/key-vault-params.json'
    deploymentMode: 'Incremental'
    # 这里可以覆盖参数文件里的参数值,比如用Pipeline变量替换name
    overrideParameters: >-
      -name "$(KeyVault.Name)"

方案二:直接传递JSON字符串(不推荐,容易踩坑)

要是你不想用参数文件,也可以试试调整变量传递的方式,但这种方式很容易因为转义问题出错,尤其是JSON里有特殊字符的时候:

  1. 先把PowerShell里的ConvertTo-Json命令去掉-Compress参数,保留格式化的JSON;
  2. 在Pipeline的overrideParameters里,用双引号把变量包起来,确保内部的双引号能被正确解析:
overrideParameters: >-
  -name "$(KeyVault.Name)"
  -fooBar "$(Infra.KeyVault.AccessPolicies)"

不过还是那句话,这种方式不如参数文件稳定,能不用就不用。

内容的提问来源于stack exchange,提问作者Dr Schizo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:22:28