title: Problems parsing / accessing nested JSON / Hashtable data via variables in Powershell
body: <p>I'm trying to dynamically parse &amp; build-up a data structure of some incoming JSON files I'm to be supplied with (that'll be in non-standard structure) via Powershell to then process the data in those files &amp; hand them over to the next step.</p>
  
  <p>As part of that, I'm trying to build up the data structure of the JSON file into essentially a list of of data-paths for me to parse through &amp; grab the data out of, so that I can cope with arrays, nested JSON objects and so on. So far so good.</p>
  
  <p>Where I fall into some sort of Powershell peculiarity is in handling 2+ levels of depth via a variable. Let me give you a nice code-block to demonstrate the problem...</p>
  
  <pre><code># Generate a Quick JSON file with different data types &amp; levels
  [object]$QuickJson = @'
  {
      "Name" : "I am a JSON",
      "Version" : "1.2.3.4",
      "SomeBool" : true,
      "NULLValue" : null,
      "ArrayOfVersions" : [1.0,2.0,3.0],
      "MyInteger" : 69,
      "NestedJSON" : {
          "Version" : 5.0,
          "IsReady" : false
      },
      "DoubleNestedJSON" : {
          "FirstLevel" : 1,
          "DataValue" : "I am at first nested JSON level!",
          "Second_JSON_Level" : {
              "SecondLevel" : 2,
              "SecondDataValue" : "I am on the 2nd nested level"
          }
      }
  }
  '@
  
  # Import our JSON file into Powershell
  [object]$MyPSJson = ConvertFrom-Json -InputObject $QuickJson
  # Two quick string variables to access our JSON data paths
  [string]$ShortJsonPath = "Name"
  [string]$NestedJsonPath = "NestedJson.Version"
  # Long string to access a double-nested JSON object
  [string]$LongNestedJsonPath = "DoubleNestedJSON.Second_JSON_Level.SecondDataValue"
  
  # Both of these work fine
  Write-Host ("JSON Name (Direct) ==&gt; " + $MyPSJson.Name)
  Write-Host ("JSON Name (via Variable) ==&gt; " + $MyPSJson.$ShortJsonPath)
  
  # The following way to access a single nested Json Path works fine
  Write-Host ("Nested JSON Version (via direct path) ==&gt; " + $MyPSJson.NestedJson.Version)
  # And THIS returns an empty line / is where I fall afoul of something in Powershell
  Write-Host ("Nested JSON Version (via variable) ==&gt; " + $MyPSJson.$NestedJsonPath)
  
  # Other things I tried -- all returning an empty line / failing in effect
  Write-Host ("Alternate Nested JSON Version ==&gt; " + $($MyPSJson.$NestedJsonPath))
  Write-Host ("Alternate Nested JSON Version ==&gt; " + $MyPSJson.$($NestedJsonPath))
  Write-Host ("Alternate Nested JSON Version ==&gt; " + $($MyPSJson).$($NestedJsonPath))
  
  # Similarly, while THIS works...
  $MyPSJson | select-object -Property NestedJSON
  # This will fail / return me nothing
  $MyPSJson | select-object -Property NestedJSON.Version
  </code></pre>
  
  <p>... in doing a bunch of research around this, I came across a suggestion to transform this into a Hashtable -- but that has the same problem, sadly. So with the above code-snippet, the following will transform the JSON object into a hashtable.</p>
  
  <pre><code># Same problem with a hash-table if constructed from the JSON file...
  [hashtable]$MyHash = @{}
  # Populate $MyHash with the data from our quickie JSON file...
  $QuickJson | get-member -MemberType NoteProperty | Where-Object{ -not [string]::IsNullOrEmpty($QuickJson."$($_.name)")} | ForEach-Object {$MyHash.add($_.name, $QuickJson."$($_.name)")}
  
  # ... and even then -- $MyHash."$($NestedJsonPath)" -- fails, while a single level deep string works fine in the variable! :(
  </code></pre>
  
  <p>So it's pretty clear that I'm running into "something" of a Powershell internal logic problem, but I can't get Powershell to be overly helpful in WHY that is. Adding a '-debug' or similar in an attempt to increase verbosity hasn't helped shed light on this.</p>
  
  <p>I suspect it's something akin to the items raised in this article here ( <a href="https://blogs.technet.microsoft.com/heyscriptingguy/2011/10/16/dealing-with-powershell-hash-table-quirks/" rel="nofollow noreferrer">https://blogs.technet.microsoft.com/heyscriptingguy/2011/10/16/dealing-with-powershell-hash-table-quirks/</a> ) but just specific with variables.</p>
  
  <p>I've not had any luck in finding anything obvious in the Powershell language specification (3.0 still being the latest from here as far as I can tell -- <a href="https://www.microsoft.com/en-usdownload/details.aspx?id=36389" rel="nofollow noreferrer">https://www.microsoft.com/en-usdownload/details.aspx?id=36389</a> ) either. It may be in there, I may just miss it.</p>
  
  <p>Any advice in how to get Powershell to play nice with this would be greatly appreciated. I'm not sure how / why Powershell is fine with a simple string but seems to have issues with a 'something.somethingelse' type string here.</p>
  
  <p>Thank you.</p>
  
  <p><strong>Further notes &amp; addenda to the original:</strong></p>
  
  <p>It seems there are several issues to attack. One is "dealing with a single nested level". The "quick fix" for that seems to be using "Invoke-Expression" to resolve the statement, so for instance (IMPORTANT - take note of the back-tick with the first variable!):</p>
  
  <pre><code>iex "`$MyPSJson.$NestedJsonPath"
  </code></pre>
  
  <p>That use of Invoke-Expression also works with multi-nested situations:</p>
  
  <pre><code>iex "`$MyPSJson.$LongNestedJsonPath"
  </code></pre>
  
  <p>An alternative approach that was mentioned is the use of multiple select statements ... but I've not been able to get that to work with multi-nested objects (Powershell seems to not resolve those properly for some reason).</p>
  
  <p>So for instance in this scenario:</p>
  
  <pre><code>($MyComp | select $_.DoubleNestedJSON | select FirstLevel)
  </code></pre>
  
  <p>Powershell returns</p>
  
  <pre><code>FirstLevel    
  ---------- 
  </code></pre>
  
  <p>... instead of the actual data value. So - for now, it seems that selects won't work with multi-level nested objects due to Powershell apparently not resolving them?</p>