Powershell 7 合并复杂的 Json => 将带有“路径”信息的 PSCustomObject 转换为 json

问题描述 投票:0回答:1

我使用这篇文章中的 Get-LeafProperty 转换了两个 json 文件 Powershell 从对象中选择 NoteProperty 类型对象

这使得合并2个包含不同general.apps[]的json文件变得很容易,至少合并由Get-LeafProperty创建的psobject很容易。

现在我想从合并的 psobjects 返回到原始的 json 格式。

我有一个像这样的 psobject,我喜欢将其转换为 json。

`

[path]                                                                                              : [value]
general.apps[0].name                                                                                 : admin
general.apps[0].storageAccount.sku.name                                                              : Standard_LRS
general.apps[0].storageAccount.sku.tier                                                              : Standard
general.apps[0].hostingPlan.sku.name                                                                 : Y1
general.apps[0].hostingPlan.sku.tier                                                                 : Dynamic
general.apps[0].appconfig.AzureWebJobsDisableHomepage                                                : True
general.apps[0].appconfig.AzureWebJobsStorage__accountName                                           : ${Prefix}${tier}admin
general.apps[0].appconfig.CosmosDbConnectionStringOrManagedIdentity                                  : AccountEndpoint=https://${Prefix}${tier}cosmosdb.documents.azure.com:443
general.apps[0].appconfig.cpo-blackbox-authorization-token                                           : 
general.apps[0].appconfig.DatabaseCacheRefreshMinutes                                                : 
general.apps[0].appconfig.HttpCallMaxSeconds                                                         : 
general.apps[0].appconfig.EvgCpoOcpiUrl                                                              : https://${Prefix}${tier}${staging}cpoocpi.azurewebsites.net/api/
general.apps[0].appconfig.EvgCtrlWpsUrl                                                              : https://${Prefix}${tier}${staging}ctrlwps.azurewebsites.net/api/
general.apps[0].appconfig.EvgPingUrl                                                                 : https://${Prefix}${tier}${staging}ping.azurewebsites.net/api/
general.apps[0].appconfig.Logging___DebugAsInformation                                               : 
general.apps[0].appconfig.Logging___TraceAsInformation                                               : 
general.apps[0].appconfig.NegotiatePostfix                                                           : /webpubsub/v100/negotiate
general.apps[0].appconfig.OcpiAuthenticationFailureDelayBaseMilliseconds                             : 
general.apps[0].appconfig.OcpiEvgCountryCode                                                         : 
general.apps[0].appconfig.OcpiLocationSuppressEvents                                                 : True
general.apps[0].appconfig.OcpiEvgPartyId                                                             : 
general.apps[0].appconfig.OcpiSessionTokenMaxAgeSeconds                                              : 
general.apps[0].appconfig.OCPIv211___GetPagingLimit                                                  : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Cdr___Disconnected___TimerCheckConnection               : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Cdr___Pump___TimerCheckConnection                       : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Cdr___Pump___TimerResponse                              : 
general.apps[0].appconfig.OCPPv16_OCPIv211___LocationEvse___Disconnected___TimerCheckConnection      : 
general.apps[0].appconfig.OCPPv16_OCPIv211___LocationEvse___Pump___TimerCheckConnection              : 
general.apps[0].appconfig.OCPPv16_OCPIv211___LocationEvse___Pump___TimerResponse                     : 
general.apps[0].appconfig.OCPPv16_OCPIv211___SessionRecovery___TimerDelayRecoveryRepeatSec           : 
general.apps[0].appconfig.OCPPv16_OCPIv211___SessionRecovery___TimerDelayRecoveryShotSec             : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___Default___TimerExitSec                   : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___Default___TimerRecoverySec               : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___StartSessionState___TimerExitSec         : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___StartSessionRecoveryState___TimerExitSec : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___WaitPatchSessionState___TimerExitSec     : 
general.apps[0].appconfig.OCPPv16_OCPIv211___Statemachine___WaitPatchSessionState___TimerRecoverySec : 
general.apps[0].appconfig.PingUrls                                                                   : 
general.apps[0].appconfig.SCALE_CONTROLLER_LOGGING_ENABLED                                           : 
general.apps[0].appconfig.ServiceBusConnectionString__fullyQualifiedNamespace                        : 
general.apps[0].appconfig.ServiceBusQueueList                                                        : cpoocpi:ctrlwps
general.apps[0].appconfig.ServiceBusName                                                             : 
general.apps[0].appconfig.StatemachineCheckAgeCronSchedule                                           : 
general.apps[0].appconfig.StatemachineCheckAgeMinAgeDays                                             : 
general.apps[0].appconfig.StatemachineEngineDatabase                                                 : 
general.apps[0].appconfig.StatemachineEngineContainerData                                            : 
general.apps[0].appconfig.StatemachineEngineContainerOperations                                      : 
general.apps[0].appconfig.StatemachineEngineContainerOperationsLeases                                : 
general.apps[0].appconfig.StatemachineEngineQueueTimers                                              : 
general.apps[0].appconfig.StatemachineEngineServiceBusQueueOperations                                : 
general.apps[0].appconfig.TimerKeepAliveCronSchedule                                                 : 0 * * * * *
general.apps[0].appconfig.TimerOcpiSessionTokenCleanupCronSchedule                                   : 
general.apps[0].appconfig.TimerOcpiV211GetCdrsCronSchedule                                           : 
general.apps[0].appconfig.TimerOcpiV211GetLocationsCronSchedule                                      : 
general.apps[0].appconfig.TimerTriggerCronSchedule                                                   : 
general.apps[0].appconfig.WebPubSubEndpoint                                                          : 
general.apps[0].appconfig.WebPubSubIdentityObjectId                                                  : 
general.apps[0].appconfig.WebPubSubConnectionString                                                  : 
general.apps[0].appconfig.WebPubSubHub                                                               : 
general.apps[0].appconfig.WebPubSubHubLogging                                                        : 
general.apps[0].appconfig.WsHostname                                                                 : ${Prefix}${tier}admin.azurewebsites.net
general.apps[1].name                                                                                 : blackboxtestapi
general.apps[1].storageAccount.sku.name                                                              : Standard_LRS
general.apps[1].storageAccount.sku.tier                                                              : Standard
general.apps[1].hostingPlan.sku.name                                                                 : Y1
general.apps[1].hostingPlan.sku.tier                                                                 : Dynamic
general.apps[1].appconfig.AzureWebJobsDisableHomepage                                                : True
general.apps[1].appconfig.AzureWebJobsStorage__accountName                                           : ${Prefix}${tier}blackboxtestapi
general.apps[1].appconfig.CosmosDbConnectionStringOrManagedIdentity                                  : 
general.apps[1].appconfig.cpo-blackbox-authorization-token                                           : 
general.apps[1].appconfig.DatabaseCacheRefreshMinutes                                                : 
general.apps[1].appconfig.HttpCallMaxSeconds                                                         : 
general.apps[1].appconfig.EvgCpoOcpiUrl                                                              : 
general.apps[1].appconfig.EvgCtrlWpsUrl                                                              : 
general.apps[1].appconfig.EvgPingUrl                                                                 : 
general.apps[1].appconfig.Logging___DebugAsInformation                                               : 
general.apps[1].appconfig.Logging___TraceAsInformation                                               : 
general.apps[1].appconfig.NegotiatePostfix                                                           : 
general.apps[1].appconfig.OcpiAuthenticationFailureDelayBaseMilliseconds                             : 
general.apps[1].appconfig.OcpiEvgCountryCode                                                         : 
general.apps[1].appconfig.OcpiEvgPartyId                                                             : 
general.apps[1].appconfig.OcpiLocationSuppressEvents                                                 : True
general.apps[1].appconfig.OcpiSessionTokenMaxAgeSeconds                                              : 
general.apps[1].appconfig.OCPIv211___GetPagingLimit                                                  : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Cdr___Disconnected___TimerCheckConnection               : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Cdr___Pump___TimerCheckConnection                       : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Cdr___Pump___TimerResponse                              : 
general.apps[1].appconfig.OCPPv16_OCPIv211___LocationEvse___Disconnected___TimerCheckConnection      : 
general.apps[1].appconfig.OCPPv16_OCPIv211___LocationEvse___Pump___TimerCheckConnection              : 
general.apps[1].appconfig.OCPPv16_OCPIv211___LocationEvse___Pump___TimerResponse                     : 
general.apps[1].appconfig.OCPPv16_OCPIv211___SessionRecovery___TimerDelayRecoveryRepeatSec           : 
general.apps[1].appconfig.OCPPv16_OCPIv211___SessionRecovery___TimerDelayRecoveryShotSec             : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___Default___TimerExitSec                   : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___Default___TimerRecoverySec               : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___StartSessionState___TimerExitSec         : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___StartSessionRecoveryState___TimerExitSec : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___WaitPatchSessionState___TimerExitSec     : 
general.apps[1].appconfig.OCPPv16_OCPIv211___Statemachine___WaitPatchSessionState___TimerRecoverySec : 
general.apps[1].appconfig.PingUrls                                                                   : 
general.apps[1].appconfig.SCALE_CONTROLLER_LOGGING_ENABLED                                           : 
general.apps[1].appconfig.ServiceBusConnectionString__fullyQualifiedNamespace                        : 
general.apps[1].appconfig.ServiceBusQueueList                                                        : 
general.apps[1].appconfig.ServiceBusName                                                             : 
general.apps[1].appconfig.StatemachineCheckAgeCronSchedule                                           : 
general.apps[1].appconfig.StatemachineCheckAgeMinAgeDays                                             : 
general.apps[1].appconfig.StatemachineEngineDatabase                                                 : 
general.apps[1].appconfig.StatemachineEngineContainerData                                            : 
general.apps[1].appconfig.StatemachineEngineContainerOperations                                      : 
general.apps[1].appconfig.StatemachineEngineContainerOperationsLeases                                : 
general.apps[1].appconfig.StatemachineEngineQueueTimers                                              : 
general.apps[1].appconfig.StatemachineEngineServiceBusQueueOperations                                : 
general.apps[1].appconfig.TimerKeepAliveCronSchedule                                                 : 0 * * * * *
general.apps[1].appconfig.TimerOcpiSessionTokenCleanupCronSchedule                                   : 
general.apps[1].appconfig.TimerOcpiV211GetLocationsCronSchedule                                      : 
general.apps[1].appconfig.TimerOcpiV211GetCdrsCronSchedule                                           : 
general.apps[1].appconfig.TimerTriggerCronSchedule                                                   : 
general.apps[1].appconfig.WebPubSubConnectionString                                                  : 
general.apps[1].appconfig.WebPubSubEndpoint                                                          : 
general.apps[1].appconfig.WebPubSubIdentityObjectId                                                  : 
general.apps[1].appconfig.WebPubSubHub                                                               : blackboxtest
general.apps[1].appconfig.WebPubSubHubLogging                                                        : logging

`

我想将这个对象转换为json。 ConvertTo-Json 给了我这个 =>

`

{
  "general.apps[0].name": "admin",
  "general.apps[0].storageAccount.sku.name": "Standard_LRS",
  "general.apps[0].storageAccount.sku.tier": "Standard",
  "general.apps[0].hostingPlan.sku.name": "Y1",
  "general.apps[0].hostingPlan.sku.tier": "Dynamic",
  <snip>

`

但是我想要得到这样的东西。

`

{ 
  "general": {
    "apps":[
      {
        "name": "admin",
        "storageAccount":
        {
          "sku": {
            "name": "Standard_LRS",      
            "tier": "Standard"
          },
          "queues": []            
        },
        "hostingPlan":{
            "sku": {
              "name": "Y1",
              "tier": "Dynamic"
            }
        },
        "insight": {},
        "appconfig": {
          "AzureWebJobsDisableHomepage": true,
          "AzureWebJobsStorage__accountName": "${Prefix}${tier}admin",

     <snip>

`

我可以在 Path 变量上运行循环并将其拆分为“.”并尝试再次创建路径。 我想知道是否有更简单的解决方案。

json powershell foreach merge object-graph
1个回答
0
投票

我用不同的方式解决了这个问题。 我没有使用 Get-Leafeproperty 进行合并,而是使用直接合并 json 的脚本。 下一个函数可以很好地合并复杂的 json。

function Merge-Json( $source, $extend ){
if( $source -is [PSCustomObject] -and $extend -is [PSCustomObject] ){

    # Ordered hashtable for collecting properties
    $merged = [ordered] @{}

    # Copy $source properties or overwrite by $extend properties recursively
    foreach( $Property in $source.PSObject.Properties ){
        if( $null -eq $extend.$($Property.Name) ){
            $merged[ $Property.Name ] = $Property.Value
        }
        else {
            $merged[ $Property.Name ] = Merge-Json $Property.Value $extend.$($Property.Name)
        }
    }

    # Add $extend properties
    foreach( $Property in $extend.PSObject.Properties ){
        if( $null -eq $source.$($Property.Name) ) {
            $merged[ $Property.Name ] = $Property.Value
        }
    }

    # Convert hashtable into PSCustomObject and output
    [PSCustomObject] $merged
}
elseif( $source -is [Collections.IList] -and $extend -is [Collections.IList] ){

    $maxCount = [Math]::Max( $source.Count, $extend.Count )

    [array] $merged = for( $i = 0; $i -lt $maxCount; ++$i ){
        if( $i -ge $source.Count ) { 
            # extend array is bigger than source array
            $extend[ $i ]
        }              
        elseif( $i -ge $extend.Count ) {
            # source array is bigger than extend array
            $source[ $i ]
        }
        else {
            # Merge the elements recursively
            Merge-Json $source[$i] $extend[$i]
        }
    }

    # Output merged array, using comma operator to prevent enumeration 
    , $merged
}
else{
    # Output extend object (scalar or different types)
    $extend
}
}
© www.soinside.com 2019 - 2024. All rights reserved.