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

PowerShell读写JSON文件时如何保留元素原始顺序?

问题

读取一个JSON文件,更新部分值后将其写回,但部分元素顺序发生了错乱。使用的PowerShell代码如下:

$manifest = (gc $manifestPath -raw) | ConvertFrom-Json -AsHashtable
$manifest.name = "$($manifest.name)-sxs"
$manifest | ConvertTo-Json -depth 100 | Out-File $manifestPath -Encoding utf8NoBOM

原始文件中的JSON片段:

{
            "name": "vsVersion",
            "type": "pickList",
            "label": "Visual Studio Version",
            "required": false,
            "helpMarkDown": "If the preferred version cannot be found, the latest version found will be used instead.",
            "defaultValue": "latest",
            "options": {
                "latest": "Latest",
                "17.0": "Visual Studio 2022",
                "16.0": "Visual Studio 2019",
                "15.0": "Visual Studio 2017",
                "14.0": "Visual Studio 2015",
                "12.0": "Visual Studio 2013",
                "11.0": "Visual Studio 2012"
            }
        },

写回后的JSON片段:

{
      "required": false,
      "type": "pickList",
      "name": "vsVersion",
      "options": {
        "11.0": "Visual Studio 2012",
        "12.0": "Visual Studio 2013",
        "14.0": "Visual Studio 2015",
        "17.0": "Visual Studio 2022",
        "15.0": "Visual Studio 2017",
        "16.0": "Visual Studio 2019",
        "latest": "Latest"
      },
      "helpMarkDown": "If the preferred version cannot be found, the latest version found will be used instead.",
      "label": "Visual Studio Version",
      "defaultValue": "latest"
    },

请问有没有办法保留元素的原始顺序?

解决方案

问题根源

你使用了-AsHashtable参数,PowerShell中的常规哈希表(Hashtable)不保留键的原始顺序,转成JSON时键的排列会被打乱。要保留顺序,需使用有序结构来处理JSON数据。

方法一:直接使用PSCustomObject(最简单)

去掉-AsHashtable参数,ConvertFrom-Json默认会将JSON对象转换为PSCustomObject,它会严格保留原始键的顺序:

$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json
$manifest.name = "$($manifest.name)-sxs"
$manifest | ConvertTo-Json -Depth 100 | Out-File $manifestPath -Encoding utf8NoBOM

这种方式适合大多数场景,PSCustomObject支持点语法修改属性,嵌套层级的顺序也会自动保留。

方法二:递归转换为有序字典(灵活控制场景)

如果需要更灵活的哈希表操作(比如动态增删键),可以将JSON递归转换为OrderedDictionary(有序字典),确保所有层级的键顺序都被保留:

# 递归转换PSCustomObject为有序字典的函数
function ConvertTo-OrderedJson {
    param(
        [Parameter(ValueFromPipeline)]
        $InputObject
    )
    process {
        if ($InputObject -is [PSCustomObject]) {
            $orderedDict = [ordered]@{}
            foreach ($prop in $InputObject.PSObject.Properties) {
                $orderedDict[$prop.Name] = $prop.Value | ConvertTo-OrderedJson
            }
            return $orderedDict
        }
        elseif ($InputObject -is [array]) {
            return $InputObject | ForEach-Object { $_ | ConvertTo-OrderedJson }
        }
        else {
            return $InputObject
        }
    }
}

# 读取并处理JSON
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json | ConvertTo-OrderedJson
$manifest.name = "$($manifest.name)-sxs"
$manifest | ConvertTo-Json -Depth 100 | Out-File $manifestPath -Encoding utf8NoBOM

注意事项

  • PowerShell 5.1及以上版本中,ConvertTo-Json处理PSCustomObject或OrderedDictionary时,会保留键的原始顺序
  • 绝对避免使用常规Hashtable存储JSON数据,它的键顺序由哈希算法决定,无法保证一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:27:28