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

PowerShell中向JSON文件添加HashTable的正确方法及优化方案咨询

问题描述

我有如下哈希表:

$a = @{
"computer1" = @{
    "app1" = "2023.04.04"
    "app2" = "2022.07.11"
}}

需要将其添加到文件$jsonReportPath = "./report.json"中,要求:

  • 添加前文件可能不存在
  • 封装为函数,接收哈希表作为参数
  • 仅当哈希表的键(如示例中的"computer1")未在JSON文件中存在时,才执行添加操作
  • 不替换现有内容,仅新增条目

例如初始JSON内容:

{
  "computer": {
    "program": "22.9.0.135",
    "program1": "4.0.1.23758"
  },
  "computer0": {
    "program": "22.5.0.135",
    "program1": "4.7.1.23758"
  }
}

添加后应变为:

{
  "computer": {
    "program": "22.9.0.135",
    "program1": "4.0.1.23758"
  },
  "computer0": {
    "program": "22.5.0.135",
    "program1": "4.7.1.23758"
  },
  "computer1": {
    "app1": "2023.04.04",
    "app2": "2022.07.11"
  }
}

我自己编写了一个函数,但觉得实现略显繁琐,想了解更优、更规范的写法:

function AddItemToJsonReport([Hashtable]$item) {
    $jsonReportPath = "C:\path\to\json\report.json"
    $report = Get-Content -Path $jsonReportPath -Raw | ConvertFrom-Json -AsHashtable
    if (-not $report) {
        $report = @{}
    } # If the json report is empty, initialize it as an empty hashtable
    $nodeName = $item.PSObject.Properties.Name # Get the key of the hashtable, the node name
    # If the node already exists in the json report, don't add it again
    if ($report.ContainsKey($nodeName)) { return }
    $item.GetEnumerator() | ForEach-Object {
        $report[$.Key] = $.Value
    }
    $updatedJsonReport = ConvertTo-Json $report -Depth 100
    $fileExists = Test-Path $jsonReportPath
    if ($fileExists) {
        Out-File -FilePath $jsonReportPath -InputObject $updatedJsonReport -Encoding utf8
    }
}
优化后的实现

以下是更简洁规范的函数版本,解决了原代码的冗余问题,同时完善了边界场景处理:

function Add-ComputerToJsonReport {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [Hashtable]$ComputerData,
        [string]$JsonPath = "./report.json"
    )

    # 读取现有JSON或初始化空哈希表
    $report = if (Test-Path $JsonPath) {
        Get-Content -Path $JsonPath -Raw | ConvertFrom-Json -AsHashtable -ErrorAction SilentlyContinue
    }
    $report ??= @{}

    # 获取传入哈希表的唯一键(假设传入的是单键哈希表)
    $computerName = $ComputerData.Keys | Select-Object -First 1
    if (-not $computerName) { return }

    # 检查键是否已存在,存在则直接返回
    if ($report.ContainsKey($computerName)) {
        Write-Verbose "计算机 $computerName 已在报告中,跳过添加"
        return
    }

    # 添加新条目并写入文件
    $report[$computerName] = $ComputerData[$computerName]
    $report | ConvertTo-Json -Depth 100 | Set-Content -Path $JsonPath -Encoding UTF8
}
优化点说明
  • 参数化设计:将文件路径设为可选参数,提升函数的复用性和灵活性
  • 简化初始化逻辑:使用PowerShell 7+的??=空合并赋值运算符,替代冗余的if判断,代码更简洁
  • 高效获取键:直接通过$ComputerData.Keys获取哈希表键,比PSObject.Properties.Name更直观高效
  • 简化写入流程:使用Set-Content替代Out-File,无需单独判断文件是否存在(Set-Content会自动创建不存在的文件)
  • 调试友好:添加Write-Verbose输出,便于跟踪执行状态
  • 符合命名规范:采用PowerShell标准的动词-名词函数命名格式(Add-ComputerToJsonReport),可读性更强
  • 错误处理优化:添加-ErrorAction SilentlyContinue,避免文件为空或格式异常时的转换报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:45:17