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

如何在PowerShell中合并两个JSON的Jobs对象并保留原父结构?

问题描述

我有两个结构相似的JSON文件,需要从第一个JSON的Jobs数组中提取所有元素,并追加到第二个JSON的同名Jobs数组下。目前已成功提取并合并两个JSON的Jobs内容,但无法在不丢失Jobs以外原有父对象的前提下直接更新第二个JSON。注意:JSON根节点的属性名并非始终以DBM开头。

第一个JSON(源JSON)

{
  "DBM0003": {
  "Type":  "Folder",
  "ControlmServer": "vl-aus-dbaqa001",
  "ActiveRetentionPolicy": "CleanEndedOK",
  "SubApplication": "VSAUSUBAPP",
  "CreatedBy": "emuser",
  "Application": "VSAUAPP",
  "Jobs": [
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "hostname",
      "Name": "DBMAU001",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU001-273"
          }
        ]
      },
      "eventsToAdd": {
        "Type": "AddEvents",
        "Events": [
          {
            "Event": "DBMAU001-TO-DBMAU002-341"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU001-273"
          }
        ]
      }
    },
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "cat $HOME/installed-versions.txt",
      "Name": "DBMAU002",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "DBMAU001-TO-DBMAU002-341"
          }
        ]
      },
      "eventsToAdd": {
        "Type": "AddEvents",
        "Events": [
          {
            "Event": "DBMAU002-TO-DBMAU003-341"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "DBMAU001-TO-DBMAU002-341"
          }
        ]
      }
    },
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "cat $HOME/installed-versions.txt",
      "Name": "DBMAU003",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "DBMAU002-TO-DBMAU003-341"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "DBMAU002-TO-DBMAU003-341"
          }
        ]
      }
    }
  ],
  "When": {
    "RuleBasedCalendars": {
      "Included": [
        "CAP_0001"
      ],
      "CAP_0001": {
        "Type": "Calendar:RuleBased",
        "When": {
          "DaysRelation": "OR",
          "WeekDays": [
            "NONE"
          ],
          "MonthDays": [
            "ALL"
          ]
        }
      }
    }
  }
  }
}

第二个JSON(目标JSON)

{
  "DBM0002": {
  "Type":  "Folder",
  "ControlmServer": "vl-aus-dbaqa001",
  "ActiveRetentionPolicy": "CleanEndedOK",
  "SubApplication": "VSAUSUBAPP",
  "CreatedBy": "emuser",
  "Application": "VSAUAPP",
  "Jobs": [
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "hostname",
      "Name": "DBMAU004",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU004"
          }
        ]
      },
      "eventsToAdd": {
        "Type": "AddEvents",
        "Events": [
          {
            "Event": "DBMAU004-TO-DBMAU005"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU004"
          }
        ]
      }
    },
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "hostname",
      "Name": "DBMAU004",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU004"
          }
        ]
      },
      "eventsToAdd": {
        "Type": "AddEvents",
        "Events": [
          {
            "Event": "DBMAU004-TO-DBMAU005"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "CAPU003-TO-DBMAU004"
          }
        ]
      }
    },
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "cat $HOME/installed-versions.txt",
      "Name": "DBMAU005",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "DBMAU004-TO-DBMAU005"
          }
        ]
      },
      "eventsToAdd": {
        "Type": "AddEvents",
        "Events": [
          {
            "Event": "DBMAU005-TO-DBMAU006"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "DBMAU004-TO-DBMAU005"
          }
        ]
      }
    },
    {
      "Type": "Job:Command",
      "SubApplication": "VSAUSUBAPP",
      "CreatedBy": "emuser",
      "Description": "Test Job",
      "RunAs": "ctmagent",
      "Application": "VSAUAPP",
      "Command": "cat $HOME/installed-versions.txt",
      "Name": "DBMAU006",
      "When": {
        "WeekDays": [
          "NONE"
        ],
        "MonthDays": [
          "ALL"
        ],
        "DaysRelation": "OR",
        "RuleBasedCalendars": {
          "Relationship": "AND",
          "Included": [
            "CAP_0001"
          ]
        }
      },
      "eventsToWaitFor": {
        "Type": "WaitForEvents",
        "Events": [
          {
            "Event": "DBMAU005-TO-DBMAU006"
          }
        ]
      },
      "eventsToDelete": {
        "Type": "DeleteEvents",
        "Events": [
          {
            "Event": "DBMAU005-TO-DBMAU006"
          }
        ]
      }
    }
  ],
  "When": {
    "RuleBasedCalendars": {
      "Included": [
        "CAP_0001"
      ],
      "CAP_0001": {
        "Type": "Calendar:RuleBased",
        "When": {
          "DaysRelation": "OR",
          "WeekDays": [
            "NONE"
          ],
          "MonthDays": [
            "ALL"
          ]
        }
      }
    }
  }
  }
}

当前PowerShell脚本

$sourcejson = Get-Content 'DBM0002.json' | ConvertFrom-Json
$destjson = Get-Content 'DBM0003.json' | ConvertFrom-Json

$sourcefolder = $sourcejson.PsObject.Properties.Name
$sourcejobs = $sourcejson.$($sourcefolder).Jobs
$sourcejobsjson = $sourcejobs | ConvertTo-Json -Depth 99
$sourcejobsnames = $sourcejson.$($sourcefolder).Jobs.Name
$sourcejobscount = $sourcejson.$($sourcefolder).Jobs.Name.Count

$destfolder = $destjson.PsObject.Properties.Name
$destjobs = $destjson.$($destfolder).Jobs
$destjobsjson = $destjobs | ConvertTo-Json -Depth 99
$destjobsnames = $destjson.$($destfolder).Jobs.Name
$destjobscount = $destjson.$($destfolder).Jobs.Name.Count

$destjobs += $sourcejobs
$destjobs | ConvertTo-Json -Depth 99 | Add-Content -Path Combined.json


$sourcejson = Get-Content 'DBM0002.json' | ConvertFrom-Json
$destjson = Get-Content 'DBM0003.json' | ConvertFrom-Json

$sourcefolder = @($sourcejson.PsObject.Properties)[0].Name
$sourcejobs = @($sourcejson.PSObject.Properties)[0].Value.Jobs
$sourcejobsnames = @($sourcejson.PSObject.Properties)[0].Value.Jobs.Name
$sourcejobscount = @($sourcejson.PSObject.Properties)[0].Value.Jobs.Name.Count

$destfolder = @($destjson.PsObject.Properties)[0].Name
$destjobs = @($destjson.PSObject.Properties)[0].Value.Jobs
$destjobsnames = @($destjson.PSObject.Properties)[0].Value.Jobs.Name
$destjobscount = @($destjson.PSObject.Properties)[0].Value.Jobs.Name.Count

# Option 1
$destjobs += $sourcejobs
# Option 2
@($destjson.PSObject.Properties)[0].Value.Jobs += @(@($sourcejson.PSObject.Properties)[0].Value.Jobs)
# Option 3
@($destjson.PSObject.Properties)[0].Value.Jobs += @($sourcejson.PSObject.Properties)[0].Value.Jobs
$destjson | ConvertTo-Json -Depth 99 | Add-Content -Path Combined.json


Write-Host $sourcefolder","$sourcejobscount"," -NoNewline && Write-Host $sourcejobsnames -Separator ":"
Write-Host $destfolder","$destjobscount"," -NoNewline && Write-Host $destjobsnames -Separator ":"
解决方案

核心问题在于直接对$destjobs赋值不会修改原$destjson对象的引用,需要直接操作$destjson内部的Jobs数组。以下是修正后的脚本:

# 读取并解析两个JSON文件
$sourceJson = Get-Content 'DBM0003.json' | ConvertFrom-Json
$destJson = Get-Content 'DBM0002.json' | ConvertFrom-Json

# 获取源JSON的根节点属性名(兼容非DBM开头的情况)
$sourceRootKey = @($sourceJson.PSObject.Properties)[0].Name
# 提取源JSON的Jobs数组
$sourceJobs = $sourceJson.$sourceRootKey.Jobs

# 获取目标JSON的根节点属性名
$destRootKey = @($destJson.PSObject.Properties)[0].Name
# 将源Jobs数组追加到目标Jobs数组中
$destJson.$destRootKey.Jobs += $sourceJobs

# 将合并后的目标JSON写入文件,保留所有原有属性
$destJson | ConvertTo-Json -Depth 99 | Set-Content -Path 'Combined.json'

# 输出验证信息
Write-Host "源根节点: $sourceRootKey,Jobs数量: $($sourceJobs.Count)"
Write-Host "目标根节点: $destRootKey,合并后Jobs数量: $($destJson.$destRootKey.Jobs.Count)"

关键说明

  • 直接操作$destJson.$destRootKey.Jobs,确保修改的是原$destJson对象的内部数组,而非副本。
  • 使用@($sourceJson.PSObject.Properties)[0].Name动态获取根节点属性名,兼容任意命名的根节点。
  • 使用Set-Content而非Add-Content避免重复写入内容。
  • -Depth 99确保嵌套的JSON结构被正确序列化,不会丢失层级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:44:50