This behavior is mystifying!
Consider the following PowerShell script:
[Reflection.Assembly]::LoadFrom("Newtonsoft.Json.dll") | Out-Null
function ConvertFrom-JsonNet {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string] $Json
)
$O = [Newtonsoft.Json.Linq.JObject]::Parse($Json)
Write-Host $O.GetType().Name
return $O
}
Clear-Host
$Json = '{"test":"prop"}'
$O1 = ConvertFrom-JsonNet '{"test":"prop"}'
$O2 = [Newtonsoft.Json.Linq.JObject]::Parse($Json)
Write-Host $O1.GetType().Name
Write-Host $O2.GetType().Name
You'd expect the output to be:
JObject
JObject
JObject
but it's not! It's:
JObject
JProperty
JObject
How is this possible? How is the type of the object within the function JObject
, but then after it's passed out of the function, it's JProperty
?
Sigh
Yay for PowerShell's inflexibility!
Apparently, PowerShell will "unroll" all collections that are destined for the pipeline. In this case,
JObject
implementsICollection<KeyValuePair<string, JToken>>
. TheJObject
's collection contains a singleJProperty
, which is what was being "unrolled" into the pipeline. I found this answer, which shows that rolling a collection into an outer collection will cause the intended value to be placed in the pipeline.Wouldn't it be nice if PowerShell had a mechanism for adding something to the pipeline untouched? :)