I am working on a script in PowerShell 5.1 and I got a issue that I cannot really make sense of :
@{test=@() | Where-Object {$_ -ne $null}} | ConvertTo-Json -Compres
returns
{"test":{}}
Yet
$null -eq (@() | Where-Object {$_ -ne $null})
is True
Why does ConvertTo-Json
returns an empty object on a null pipe result ?
CodePudding user response:
Two issues at play here. First, an empty pipeline is not the same thing as $null
, as explained in "Why is an empty PowerShell pipeline not the same as null?" @{test=@() | Where-Object {$_ -ne $null}}
produces a hash table with a test
key that has an AutomationNull
value, not $null
.
Second, there's a bug in PowerShell prior to 7.0 where AutomationNull
is serialized as an empty object rather than $null
, as reported in "ConvertTo-Json unexpectedly serializes AutomationValue.Null
as an empty object, not null" (powershell#9231).
To work around this bug in older versions, you can coerce the AutomationNull
to a real $null
by inserting a psobject
cast, which will then result in the value serializing properly:
@{test=[psobject](@() | Where-Object {$_ -ne $null})} | ConvertTo-Json -Compres