我使用这篇文章中的 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 变量上运行循环并将其拆分为“.”并尝试再次创建路径。 我想知道是否有更简单的解决方案。
我用不同的方式解决了这个问题。 我没有使用 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
}
}