Robert Westerlund's helpful answer shows one way of filtering out $null and '' (empty-string) values, using the Where-Object cmdlet, which coerces the output from the script block to a Boolean, causing both $null and '' evaluate to $False and thus causing them to be filtered out.
This answer shows an alternative approach and discusses other aspects of the question.
tl;dr:
@{
data = @((Get-ChildItem -Recurse Cert:\LocalMachine).FriendlyName) -notlike '' |
Sort-Object | Select-Object @{ n='{#CERTINFO}'; e={ $_ } }
} | ConvertTo-Json
Using -ne $Null i get boolean results like true or false...
You only get a Boolean if the LHS is a scalar rather than an array - in the case of an array, the matching array elements are returned.
To ensure that the LHS (or any expression or command output) is an array, wrap it in @(...) the array-subexpression operator (the following uses PSv3+ syntax ):
@((Get-ChildItem -Recurse Cert:\LocalMachine).FriendlyName) -notlike ''
Note the use of -notlike '' to weed out both $null and '' values: -notlike forces the LHS to a string, and $null is converted to ''.
By contrast, if you wanted to use -ne $null, you'd have to use -ne '' too so as to also eliminate empty strings (though, in this particular case you could get away with just -ne '', because ConvertTo-Json would simply ignore $null values in its input).
Calling .FriendlyName on the typically array-valued output of Get-ChildItem directly is a PSv3+ feature called member-access enumeration: the .FriendlyName property access is applied to each element of the array, and the results are returned as a new array.
Filtering and sorting the values before constructing the wrapper objects with the {#CERTINFO} property not only simplifies the command, but is also more efficient.
Further thoughts:
Do not use Write-Host to output data: Write-Host bypasses PowerShell's (success) output stream; instead, use Write-Output, which you rarely need to call explicitly however, because its use is implied.
- Instead of
write-host "{", use write-output "{" or - preferably - simply "{" by itself.
PowerShell supports multi-line strings (see Get-Help about_Quoting_Rules), so there's no need to output the result line by line:
@"
{
"data":
$(<your ConvertTo-Json pipeline>)
}
"@
However, given that you're invoking ConvertTo-Json anyway, it's simpler to provide the data wrapper as a PowerShell object (in the simplest form as a hashtable) to ConvertTo-Json, as shown above.