public/Merge-PSObject.ps1
|
<#
.SYNOPSIS Create a new PSObject by recursively combining the properties of PSObjects. .INPUTS System.Management.Automation.PSObject to combine. .OUTPUTS System.Management.Automation.PSObject combining the inputs. .FUNCTIONALITY PowerShell .LINK Get-Member .LINK Add-Member .EXAMPLE Merge-PSObject ([pscustomobject]@{a=1;b=2}) ([pscustomobject]@{b=0;c=3}) a b c - - - 1 2 3 .EXAMPLE Merge-PSObject ([pscustomobject]@{a=1;b=2}) ([pscustomobject]@{b=0;c=3}) -Force a b c - - - 1 0 3 .EXAMPLE '{"a":1,"b":{"u":3},"c":{"v":5}}','{"a":{"w":8},"b":2,"c":{"x":6}}' |ConvertFrom-Json |Merge-PSObject -Accumulate -Force |select -Last 1 |ConvertTo-Json { "a": { "w": 8 }, "b": 2, "c": { "v": 5, "x": 6 } } #> [CmdletBinding()][OutputType([PSObject])] Param( # Initial PSObject to combine. [Parameter(Position=0)][PSObject] $ReferenceObject = [pscustomobject]@{}, <# PSObjects to combine. PSObject descendant properties are recursively merged. Primitive values are overwritten by any matching ones in the new PSObject. #> [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true)][PSObject] $InputObject, # Continue merging each pipeline object's properties into the same accumulator object. [switch] $Accumulate, # Overwrite existing properties. [switch] $Force ) Begin {if($Accumulate) {$value = $ReferenceObject.PSObject.Copy()}} Process { if(!$Accumulate) {$value = $ReferenceObject.PSObject.Copy()} foreach($p in $InputObject |Get-Member -Type Properties) { $name,$type = $p.Name,$p.MemberType $newvalue = $InputObject.$name if(!($value |Get-Member $name -Type $type)) { $value |Add-Member $name -Type $type -Value $newvalue } elseif($Force) { $currentvalue = $value.$name $value.$name = if($currentvalue -isnot [PSObject] -or $newvalue -isnot [PSObject]) {$newvalue} else {Merge-PSObject $currentvalue $newvalue} } elseif($value.$name -is [PSObject] -and $newvalue -is [PSObject]) { $value.$name = Merge-PSObject $value.$name $newvalue } } return $value } |