Hoping that someone might be able to explain why the first removal does not affect the first variable, but the second removal does affect the first variable, please. Thank you.
$X = @'
{
"$schema": "myschema",
"parameters": {
"avSetName": {
"type": "string"
},
"faultDomains": {
"type": "int",
"defaultValue": 2
}
},
"variables": {
"templateRef": "singleavset v1",
"osProfile9": "blahblah"
},
"resources": [
{
"apiVersion": "2019-07-01",
"type": "Microsoft.Compute/availabilitySets",
"name": "[parameters('avSetName')]",
"location": "[resourceGroup().location]"
}
]
}
'@
# this affects only $B...
$A = ConvertFrom-Json -InputObject $X
$B = $A.PSObject.Copy()
$A
$B
$B.PSObject.Properties.Remove( "variables" )
$A
$B
# this affects $A and $B...
$A = ConvertFrom-Json -InputObject $X
$B = $A.PSObject.Copy()
$A
$B
$B.Variables.PSObject.Properties.Remove( "osprofile9" )
$A
$B
When loading $B, then if I simply use $B = $A then I get why $A would be affected, because PowerShell is I believe using a reference pointer behind the scenes. But, if I use $B = $A.PSObject.Copy() then I would not expect $A to be affected.
The .Copy()
method of type [pscustomobject]
creates a shallow clone (copy) of a given instance rather than a deep clone (and the type fundamentally doesn't offer deep copying).
Thus, any nested [pscustomobject]
instances in your input object - by virtue of being instances of .NET reference types - are not copied; specifically, it is a reference to them that gets copied, which means that both the input object and its copy point to (reference) the very same nested instance. See this answer for background information.
Specifically, this relates to your modifications as follows:
In your first modification, you're removing a property from the copied object: since the original object and its copy as a whole are by definition distinct instances, this removal affects the copy only.
In your second modification, you're removing a property from a property value (.Variables.PSObject.Properties.Remove( "osprofile9" )
, and that value (.Variables
) - due to being a nested [pscustomobject]
instance - is shared between the original and the copy, i.e. they both reference the very same instance. Therefore, modification of this nested instance surfaces in both the copy and the original.
Since your data source is ultimately JSON, the simplest way to create two fully independent [pscustomobject]
instances is to call ConvertFrom-Json
twice, and capture each call in a separate variable:
$A = ConvertFrom-Json $X
$B = ConvertFrom-Json $X