Here below is a PS function supposed to convert PS object to NS json.Net object.
function ConvertTo-NSJson ( $psObject ) {
$json = $psObject | ConvertTo-Json -Compress -Depth 10
$nsJson = [Newtonsoft.Json.Linq.JObject]::Parse( $json )
return $nsJson
}
Here below is a small PS object for testing
$psObject = [PSCustomObject] @{
number = 10
text = 'My message'
list = @( 'item1', 'item2', 'item3' )
hash = @{ key1 = 'text value'; key2 = 2; key3 = $true }
}
If I run each line of the function at command prompt, I get expected json.Net object.
PS > $json = $psObject | ConvertTo-Json -Compress -Depth 10
PS > $nsJson = [Newtonsoft.Json.Linq.JObject]::Parse( $json )
PS > $nsjson['text'].Value
My message
PS > $nsjson.Item('text').Value
My message
PS > $nsjson['number'].Value
10
PS > $nsjson.Item('number').Value
10
PS > $nsjson['list'][0].Value
item1
PS > $nsjson.Item('list')[0].Value
item1
PS > $nsjson['hash']['key1'].Value
text value
PS > $nsjson.Item('hash')['key1'].Value
text value
PS >
The values of the original properties are available despite the way used to get them.
If now I call the function ConvertTo-NSJson … I get also a json.Net object but somehow different from previous one.
PS > $nsjson = ConvertTo-NSJson $psobject
PS > $nsjson['text'].Value # return nothing
PS > $nsjson.Item('text').Value # generate exception
GetValueInvocationException: Exception getting "Item": "Cannot convert argument "index", with value: "text", for "get_Item" to type "System.Int32": "Cannot convert value "text" to type "System.Int32". Error: "The input string 'text' was not in a correct format."""
PS > $nsjson.ToString() # shows correct json content
{
"number": 10,
"text": "My message",
"list": [
"item1",
"item2",
"item3"
],
"hash": {
"key3": true,
"key2": 2,
"key1": "text value"
}
}
PS >
The values of the original properties are not available. The first way returns null, the second way generates exception. But the ToString output shows that nsjson object contains all properties and values.
Where is my mistake ? Why the json.Net object returned by the function do not have the same behavior ?
It seems you must cast the returned
$nsJsonto aJObjectto use its methods successfully:Demo here.
I am not entirely sure why this is necessary, but as explained in this answer by Mathias R. Jessen to Specify function return type, PowerShell commands do not have static return types. Now
JObjectimplements many different indexers both explicitly and via inheritance as well asIDynamicMetaObjectProvider, and it seems the PS interpreter is getting confused about which indexer to invoke. Specifying the type asJObjectappears to resolve the problem.Finally, note that
JObjectcan only represent a JSON object, which is a pair of curly brackets surrounding zero or more name/value pairs. If yourConvertTo-NSJsonfunction may need to parse JSON arrays or primitives, you should parse toJToken: