PowerShell在JSON文件指定位置插入新键值对
问题根因
原有代码输出不符合预期,核心是两个逻辑错误:
- 每次循环都重复读取目标JSON文件,且使用
+=直接向Services数组末尾追加元素,没有定位到第一个Name='Service1'的节点位置做定向插入 - 循环内反复读写文件,会导致前一次插入的元素位置在后续读取时偏移,最终出现新老元素穿插错位的问题。
正确实现代码
function Get-EnvironmentManifest([string]$Filename) { $Settings = Get-Content -Path $Filename -Encoding UTF8 | ConvertFrom-Json -ErrorAction STOP return $Settings } if (([System.Net.Dns]::GetHostByName($env:computerName)).HostName.Split('.')[0] -notmatch "UAT*") { $EnvironmentString = (([System.Net.Dns]::GetHostByName($env:computerName)).HostName.Split('.')[0].Split('-')[1]).ToUpper() # 仅读取一次配置文件,避免循环内反复IO导致内容错位 $Settings = Get-EnvironmentManifest -Filename $TargetJSON # 定位第一个Name为Service1的元素索引位置 $insertIndex = [array]::IndexOf($Settings.Profiles.Services.Name, 'Service1') if ($insertIndex -eq -1) { throw "Services数组中未找到Name为Service1的节点,无法执行插入" } # 批量生成所有需要新增的服务节点 $newAssets = @() for ($i = 1; $i -lt 5; $i++) { $ServiceName = 'Service' + [char](65 + $i) $Hashtable = [ordered] @{"Name" = "Service1"; "ProfileType" = "Windows"; "ServiceName" = "$ServiceName";} $Asset = New-Object -TypeName PSObject $Asset | Add-Member -NotePropertyMembers $Hashtable -TypeName 'Asset' $newAssets += $Asset } # 拆分数组后重新拼接:插入点前的元素 + 所有新增元素 + 插入点后的元素 $beforeSegment = $Settings.Profiles.Services[0..$insertIndex] $afterSegment = $Settings.Profiles.Services[($insertIndex + 1)..($Settings.Profiles.Services.Count - 1)] $Settings.Profiles.Services = $beforeSegment + $newAssets + $afterSegment # 一次性将完整结构写回文件,指定UTF8编码避免乱码 $Settings | ConvertTo-Json -Depth 3 | Set-Content -Path $TargetJSON -Encoding UTF8 }
逻辑说明
- 将JSON文件的读取、写入操作移到循环外部,全程仅做一次读、一次写,从根源避免反复IO带来的数组位置偏移问题
- 借助
[array]::IndexOf()直接定位第一个Name属性为Service1的元素下标,作为插入的基准位置 - 以插入基准点为界拆分原数组,把所有新增节点统一放在第一个
Service1节点之后、原数组后续节点之前拼接,最终输出结构和预期完全一致:所有新增的Service1项连续排列在原有第一个Service1项之后,原有的Name为E、F的节点会被移动到所有新增项的末尾。
内容的提问来源于stack exchange,提问作者Vivek Singh
相关产品推荐
相关产品推荐

