PowerShell递归函数实现JSON转点表示法求助
PowerShell实现JSON转点表示法扁平化格式
需求与示例
输入常规JSON文件(如AppSettings配置),需将嵌套结构转换为保留完整路径的扁平化格式,用点连接层级键名。
输入示例:
{ "Logging": { "MinLevel": { "Default": "Information", "Override": { "Host": "Warning" } }, "Properties": { "ApplicationName": "My App" } }, "ConnectionStrings": { "DefaultConnection": "string" } }
期望输出:
"Logging.MinLevel.Default" : "Information" "Logging.MinLevel.Override.Host" : "Warning" "Logging.Properties.ApplicationName" : "My App" "ConnectionStrings.DefaultConnection" : "string"
原递归函数问题分析
你编写的ConvertTo-DotNotation函数核心思路正确,但存在几个关键问题:
- 未正确累积当前层级的键路径,递归时未拼接父级键名
- 未收集递归返回的所有结果,也未处理非对象值的输出格式
- 循环内提前
return导致仅处理第一个属性就终止函数
完善后的递归函数
function ConvertTo-DotNotation { param( [pscustomobject] $jsonObject, [string] $separator = ":", [string] $currentPath = "" ) $results = @() # 遍历对象所有属性 foreach ($property in $jsonObject.PSObject.Properties) { $key = $property.Name $value = $property.Value # 拼接当前完整路径 $newPath = if ($currentPath) { "$currentPath.$key" } else { $key } if ($value -is [pscustomobject]) { # 递归处理嵌套对象,收集结果 $results += ConvertTo-DotNotation -jsonObject $value -separator $separator -currentPath $newPath } else { # 格式化非对象值,字符串类型添加引号 $formattedValue = if ($value -is [string]) { "`"$value`"" } else { $value } $results += "`"$newPath`" $separator $formattedValue" } } return $results } # 使用示例 $appSettings = Get-Content -Path "./AppSettingsJSON/regular_json_file.json" | ConvertFrom-Json $flattenedSettings = ConvertTo-DotNotation -jsonObject $appSettings # 输出结果 $flattenedSettings
关键改进点
- 用
$results数组收集所有输出,避免提前终止函数 - 正确拼接父级路径与当前键名,确保层级完整
- 对字符串值添加引号,保持输出格式统一
- 改用
PSObject.Properties直接获取属性,比Get-Member更高效
替代实现方案(非递归)
若不想用递归,可通过栈迭代处理嵌套对象,避免递归深度限制问题:
function ConvertTo-DotNotationIterative { param( [pscustomobject] $jsonObject, [string] $separator = ":" ) $stack = [System.Collections.Stack]::new() $stack.Push(@{ Path = ""; Object = $jsonObject }) $results = @() while ($stack.Count -gt 0) { $item = $stack.Pop() $currentPath = $item.Path $currentObj = $item.Object foreach ($property in $currentObj.PSObject.Properties) { $key = $property.Name $value = $property.Value $newPath = if ($currentPath) { "$currentPath.$key" } else { $key } if ($value -is [pscustomobject]) { $stack.Push(@{ Path = $newPath; Object = $value }) } else { $formattedValue = if ($value -is [string]) { "`"$value`"" } else { $value } $results += "`"$newPath`" $separator $formattedValue" } } } # 反转结果匹配原JSON顺序(栈为后进先出结构) return $results | Reverse } # 使用示例 $flattenedSettingsIterative = ConvertTo-DotNotationIterative -jsonObject $appSettings $flattenedSettingsIterative
内容的提问来源于stack exchange,提问作者DL3001
相关产品推荐
相关产品推荐

