Powershell: ConvertTo-JSON: Nested Object of type Newtonsoft.Json.Linq.JObject not converted to Json properly

Created on 3 Oct 2017  路  5Comments  路  Source: PowerShell/PowerShell

Used the following Azure PS commands and discovered that a Nested JObject is just being converted to an Array instead of an Object.
In the repro steps the type of $result.Outputs.mediaServiceFullInfo.Value is of type Newtonsoft.Json.Linq.JObject as you can see in the final JSON Value doesn't have the Key and Values and has a Square Bracket around it.
$result.Outputs.mediaServiceFullInfo.Value.ToString() does output the Json Snippet under Value correctly.

Steps to reproduce

[Update] : Simplified repro steps in the comments.

$resourceGroupName = 'ExampleResourceGroup'
New-AzureRmResourceGroup -Name $resourceGroupName -Location 'Central US' -Verbose -Force
$result = New-AzureRmResourceGroupDeployment -Name ExampleDeployment -ResourceGroupName $resourceGroupName `
  -TemplateUri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/media-service-output-primary-key/azuredeploy.json

$result.Outputs | ConvertTo-Json

Expected behavior

{
"mediaServiceFullInfo": {
"type": "Object",
"value": {
"primaryAuthEndpoint": "https://wamsprodglobal001acs.accesscontrol.windows.net/",
"secondaryAuthEndpoint": "https://wamsprodglobal002acs.accesscontrol.windows.net/",
"scope": "urn:windowsazuremediaservices"
}
},
"mediaServicePrimaryKey": {
"type": "String",
}
}

Actual behavior

`{
"mediaServiceFullInfo": {
"Type": "Object",
"Value": [
"https://wamsprodglobal001acs.accesscontrol.windows.net/",
"https://wamsprodglobal002acs.accesscontrol.windows.net/",
"urn:windowsazuremediaservices"
]
},
"mediaServicePrimaryKey": {
"Type": "String",
}
}

Environment data

PS C:\WINDOWS\system32> $PSVersionTable

Name Value
---- -----
PSVersion 5.1.16299.15
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.16299.15
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

Area-Cmdlets-Utility Resolution-Fixed

Most helpful comment

Here is a better formatted version of amanarneja's example

$EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$EgJObject.Add("TestValue1", "123456")
$EgJObject.Add("TestValue2", "78910")
$EgJObject.Add("TestValue3", "99999")
$dict = @{}
$dict.Add('JObject', $EgJObject)
$dict.Add('StrObject', 'This is a string Object')
$properties = @{'DictObject' = $dict; 'RandomString' = 'A quick brown fox jumped over the lazy dog'}
$object = New-Object -TypeName psobject -Property $properties
$object | ConvertTo-Json

This outputs

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject":  [
                                       "123456",
                                       "78910",
                                       "99999"
                                   ],
                       "StrObject":  "This is a string Object"
                   }
}

The expected output is

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject": {
                                       "TestValue1" : "123456"
                                       "TestValue2" : "78910",
                                       "TestValue3" : "99999"
                                   },
                       "StrObject":  "This is a string Object"
                   }
}

Also if you change the last line to $object | ConvertTo-Json -depth 4 you get the even worse output

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject":  [
                                       [
                                           [

                                           ]
                                       ],
                                       [
                                           [

                                           ]
                                       ],
                                       [
                                           [

                                           ]
                                       ]
                                   ],
                       "StrObject":  "This is a string Object"
                   }
}

All 5 comments

I had to scrub out keys from your issue. Is it possible for you to construct a simpler repro?

Hey Steve
The keys were just samples and had been modified, sorry should have mentioned that.

Here's a simple Repro :

$EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$EgJObject.Add("TestValue1", "123456")
$EgJObject.Add("TestValue2", "78910")
$EgJObject.Add("TestValue3", "99999")
$dict = @{}
$dict.Add('JObject', $EgJObject)
$dict.Add('StrObject', 'This is a string Object')
$properties = @{'DictObject' = $dict;
'RandomString' = 'A quick brown fox jumped over the lazy dog'}
$object = New-Object -TypeName psobject -Property $properties
$object | ConvertTo-Json
{
"RandomString": "A quick brown fox jumped over the lazy dog",
"DictObject": {
"JObject": [
"123456",
"78910",
"99999"
],
"StrObject": "This is a string Object"
}
}

As you can see, in this case too Under JObject, we should have gotten

"JObject": {
"TestValue1" : "123456"
...

I too am running in to this issue, the biggest time we run in to it is trying to generate compressed json from the output of a New-AzureRmResourceGroupDeployment call.

Here is a better formatted version of amanarneja's example

$EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$EgJObject.Add("TestValue1", "123456")
$EgJObject.Add("TestValue2", "78910")
$EgJObject.Add("TestValue3", "99999")
$dict = @{}
$dict.Add('JObject', $EgJObject)
$dict.Add('StrObject', 'This is a string Object')
$properties = @{'DictObject' = $dict; 'RandomString' = 'A quick brown fox jumped over the lazy dog'}
$object = New-Object -TypeName psobject -Property $properties
$object | ConvertTo-Json

This outputs

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject":  [
                                       "123456",
                                       "78910",
                                       "99999"
                                   ],
                       "StrObject":  "This is a string Object"
                   }
}

The expected output is

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject": {
                                       "TestValue1" : "123456"
                                       "TestValue2" : "78910",
                                       "TestValue3" : "99999"
                                   },
                       "StrObject":  "This is a string Object"
                   }
}

Also if you change the last line to $object | ConvertTo-Json -depth 4 you get the even worse output

{
    "RandomString":  "A quick brown fox jumped over the lazy dog",
    "DictObject":  {
                       "JObject":  [
                                       [
                                           [

                                           ]
                                       ],
                                       [
                                           [

                                           ]
                                       ],
                                       [
                                           [

                                           ]
                                       ]
                                   ],
                       "StrObject":  "This is a string Object"
                   }
}

As a work around when you import the module AzureRM.Resources it also loads Newtonsoft.Json.dll. So instead of using $result.Outputs | ConvertTo-Json you can do

[Newtonsoft.Json.JsonConvert]::SerializeObject($result.Outputs, [Newtonsoft.Json.Formatting]::Indented)

Without needing to do any additional importing of types because the library is already loaded. This will give you your expected output as a string.

Was this page helpful?
0 / 5 - 0 ratings