PowerShell使用if语句修改JSON节点值失效问题排查
故障根因
脚本失效是多个语法错误、逻辑错误共同导致的:
- 循环变量引用笔误:
foreach($filepath in %JsonFilePath)中误将变量前缀$写成%,循环逻辑本身就无法正常遍历文件列表。 - 冗余无效代码:
$JsonData.update | % { ... }属于无意义调用,PowerShell反序列化JSON得到的PSCustomObject对象没有update方法,这段包裹判断和赋值的代码根本不会执行,这是值修改逻辑完全不生效的核心原因。 - 属性访问逻辑错误:直接用
$JsonData.$nodes访问多段路径时,PowerShell会把$nodes存储的完整字符串(比如Host.Server)当成单个属性名匹配,不会自动按点逐层向下查找嵌套属性;如果属性名本身带.、:这类特殊字符,匹配会直接失败。 - 循环变量引用错误:处理第三个文件的内层循环中,遍历的单节点变量是
$node,但判断、赋值时用的是存储整个数组的$nodes变量,完全没有用到循环的单节点值;且写回文件的逻辑放在内层循环中,会导致重复写入。 - 路径写法不规范:定义的Windows路径用了双反斜杠转义,PowerShell中路径直接写单反斜杠即可,双反斜杠容易出现路径匹配失败问题。
修复后完整脚本
# 定义各JSON文件路径 $Server1 = "C:\home\file1.json" $Server2 = "C:\home\file2.json" $Server3 = "C:\home\file3.json" $allJsonFiles = $Server1, $Server2, $Server3 # 配置每个文件需要修改的节点路径、目标替换值 $fileConfig = @{ $Server1 = @{ TargetNodes = @("Host.Server") NewValue = "www.blabla.com" } $Server2 = @{ TargetNodes = @("Host.Server.Author") NewValue = "www.blabla.com" } $Server3 = @{ TargetNodes = @("Host.Server", "Host.Server:Temp") NewValue = "www.blabla.com" } } foreach ($filePath in $allJsonFiles) { # 跳过不存在的文件 if (-not (Test-Path $filePath)) { continue } # 读取并反序列化JSON $jsonData = Get-Content $filePath -Raw | ConvertFrom-Json $config = $fileConfig[$filePath] foreach ($nodePath in $config.TargetNodes) { # 按点拆分路径,逐层校验节点是否存在 $pathSegments = $nodePath -split '\.' $current = $jsonData $nodeExist = $true foreach ($seg in $pathSegments) { if ($current.PSObject.Properties.Name -contains $seg) { $current = $current.$seg } else { $nodeExist = $false break } } # 节点存在则修改值 if ($nodeExist) { $parent = $jsonData # 定位到待修改节点的父级 for ($i = 0; $i -lt $pathSegments.Count - 1; $i++) { $parent = $parent.($pathSegments[$i]) } # 给目标节点赋值 $parent.($pathSegments[-1]) = $config.NewValue } } # 序列化后写回文件,指定UTF8编码避免乱码,Depth设为32避免嵌套属性丢失 $jsonData | ConvertTo-Json -Depth 32 | Set-Content $filePath -Encoding UTF8 }
使用注意事项
- 你提供的示例JSON存在语法错误,属性之间缺少逗号分隔,运行脚本前需要先修正原始JSON格式,否则
ConvertFrom-Json会直接报错。 - 如果你的JSON中存在属性名本身带
.的场景(比如示例中Host下直接有键名为Server.Author的属性,而非Server对象下嵌套Author属性),请换用不会出现在键名中的字符(比如/)作为路径分隔符,同时把脚本中拆分路径的代码$nodePath -split '\.'改为$nodePath -split '/',对应节点路径写为Host/Server.Author即可避免路径拆分错误。 - 脚本默认用UTF8编码写回文件,如果你的业务场景需要其他编码,可以自行修改
Set-Content的Encoding参数值。
内容的提问来源于stack exchange,提问作者gfran
相关产品推荐
相关产品推荐

