I'm looking for a better solution to the following problem. This code:
$a = "{value:'1'}" | ConvertFrom-Json
$b = $null
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$b = $a
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$a.value = '2'
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$b.value = '3'
Write-Output ("a: {0} - b: {1}" -f $a, $b)
Returns this:
a: @{value=1} - b: a: @{value=1} - b: @{value=1} a: @{value=2} - b: @{value=2} a: @{value=3} - b: @{value=3}
What I need is this: after setting $b
to $a
I should be able to change $a
while $b
remains unchanged.
The only solution I could come up with is do a convert to and from JSON, like this:
$a = "{value:'1'}" | ConvertFrom-Json
$b = $null
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$b = $a | ConvertTo-Json -depth 100 | ConvertFrom-Json
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$a.value = '2'
Write-Output ("a: {0} - b: {1}" -f $a, $b)
$b.value = '3'
Write-Output ("a: {0} - b: {1}" -f $a, $b)
That returns my desired result:
a: @{value=1} - b: a: @{value=1} - b: @{value=1} a: @{value=2} - b: @{value=1} a: @{value=2} - b: @{value=3}
I'm looking for a better solution because in my real-world example the variables are large JSON files that are loaded from disk, updated and saved via a PUT to an API.
Update: PSObject.Copy()
does not solve my real-world problem because that JSON has nested objects (as Ansgar Wiechers predicted in his answer).
See this example for the difference in behaviour between ConvertTo/From-Json and PSObject.Copy():
$a = "{value:'1',nested:{foo:'original value'}}" | ConvertFrom-Json
$b = $a | ConvertTo-Json -depth 100 | ConvertFrom-Json
$a.nested.foo = 'changing $a does not change $b'
$b | ConvertTo-Json -Depth 1
$c = $a.PSObject.Copy()
$a.nested.foo = 'changing $a changes $c!'
$c | ConvertTo-Json -Depth 1
Result:
{
"value": "1",
"nested": {
"foo": "original value"
}
}
{
"value": "1",
"nested": {
"foo": "changing $a changes $c!"
}
}
Update 2: the code in the other question that my question is marked as a duplicate of does indeed work in my case (see below), but I'll stick to my ConvertTo/From-Json because it's a lot simpler...
$a = "{value:'1',nested:{foo:'original value'}}" | ConvertFrom-Json
$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $a)
$ms.Position = 0
$b = $bf.Deserialize($ms)
$ms.Close()
$a.nested.foo = 'changing $a does not change $b'
$b | ConvertTo-Json -Depth 1
Result:
{
"value": "1",
"nested": {
"foo": "original value"
}
}