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

PowerShell处理JSON数组时保留结构问题求助

保留数组结构并修正值格式的解决建议

问题概述

需要处理嵌套对象中的特定节点:当节点值为数组时,保留数组结构,并给数组中符合^\[\w+规则的元素添加前缀[。当前处理会将数组拼接为字符串,导致结构丢失,不符合预期输出。

现有代码

Get-Node 遍历函数

function Get-Node {
    [CmdletBinding()][OutputType([Object[]])] param(
      [ScriptBlock]$Where,
      [AllowNull()]   
      [Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
      [Int]$Depth = 90
    )
    process {
      if ($_ -isnot [String] -and $Depth -gt 0) {
        if ($_ -is [Collections.IDictionary]) {
          if (& $Where) { $_ }
          $_.get_Values() | Get-Node -Where $Where -Depth ($Depth - 1)
        }
        elseif ($_ -is [Collections.IEnumerable] -and $_ -isnot [String]) {
          # 排除字符串,仅处理数组/集合类型
          if (& $Where) { $_ }
          # 递归处理每个元素,保留原数组结构
          for ($i = 0; $i -lt $_.get_Count(); $i++) { 
            $_[$i] = $_[$i] | Get-Node -Where $Where -Depth ($Depth - 1)
          }
          $_ # 返回处理后的数组
        }
        elseif ($Nodes = $_.PSObject.Properties.Where{ $_.MemberType -eq 'NoteProperty' }) {
          $Nodes.ForEach{
            if (& $Where) { $_ }
            # 递归处理属性值,保留数组结构
            $_.Value = $_.Value | Get-Node -Where $Where -Depth ($Depth - 1)
          }
        }
      }
    }
  }

原调用代码

if ($content.properties.policyRule -ne $null){            
    foreach ($rule in $policyRule){
        $Node = $content.properties | Get-Node -Where {$_.name -eq $rule -and $_.value -Match "^\[\w+"} 
        $Node | ForEach-Object {
            $_.Value  = '[' + $_.Value
        }  
    }
}

当前输出 vs 期望输出

当前输出(数组被拼接为字符串)

"notIn":  "[[concat(subscription().id,'/')] [subscription().id] /"

期望输出(保留数组结构,每个元素添加前缀)

"notIn":  ["[[concat(subscription().id,'/')]", "[[subscription().id]", "/"]

修正方案

1. 调整Get-Node函数,确保数组结构不丢失

修改原函数中对IEnumerable类型的处理逻辑:

  • 增加排除String类型的判断(字符串也实现了IEnumerable,需避免误处理)
  • 处理数组元素时,直接修改原数组的对应位置,而非仅管道输出单个元素
  • 处理完数组后返回整个数组,保证结构不丢失
  • 处理NoteProperty的Value时,直接赋值处理后的结果,确保数组结构被保留

2. 修改调用代码,针对数组元素逐个处理

将原调用代码中的字符串拼接逻辑,改为分类型处理:如果是数组则遍历每个元素,给符合规则的元素添加前缀;如果是单个值则直接处理。同时调整Where条件,避免因数组整体匹配导致的误判。

修正后的调用代码:

if ($content.properties.policyRule -ne $null){            
    foreach ($rule in $policyRule){
        $Node = $content.properties | Get-Node -Where {$_.name -eq $rule} 
        $Node | ForEach-Object {
            if ($_.Value -is [Collections.IEnumerable] -and $_.Value -isnot [String]) {
                # 处理数组类型:逐个检查元素,添加前缀
                $updatedArray = $_.Value | ForEach-Object {
                    if ($_ -Match "^\[\w+") { '[' + $_ } else { $_ }
                }
                $_.Value = $updatedArray
            } else {
                # 处理单个值
                if ($_.Value -Match "^\[\w+") {
                    $_.Value = '[' + $_.Value
                }
            }
        }  
    }
}

关键说明

  • 移除原Where条件中的$_.value -Match "^\[\w+",改为在处理阶段判断单个元素是否符合规则,避免数组整体匹配导致的逻辑错误
  • 处理数组时通过ForEach-Object遍历,仅给符合^\[\w+规则的元素添加前缀[
  • 保留非数组类型值的原有处理逻辑,保证代码兼容性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:00:58