Search code examples
powershellpowershell-3.0

Getting the Keys of the nested hash tables coming from json file in powershell


This is the data in json file as abc.json

{
  "testCases": {
    "test-1": {
      "some-path": "https://",
      "folders": {
        "sample": {
          "files": "abc"
        }
      }
    },
    "test-2": {
      "some-path": "https://",
      "folders": {
        "sample": {
          "files": "def"
        }
      }
    }
  }
}

I need to print the names of the testCases which are test-1 and test-2 coming from json file

What I have tried so far

# Reading the abc.json file
$changesJsonData = Get-Content abc.json -Raw | ConvertFrom-Json

# Convert the PSCustomObject back to a hashtable
$ht2 = @{}
$changesJsonData.psobject.properties | Foreach { $ht2[$_.Name] = $_.Value}
Write-Output $ht2.Keys
foreach($testNames in $ht2.Values){
Write-Output $ht2.Key
}

Current Output

testCases

Expected Output

testCases
test-1
test-2

I am able to print the key which is single item (testCases) but unable to print the values which are multiple items (test-1 and test-2)


Solution

  • You are almost there. The problem is rooted here:

    foreach($testNames in $ht2.Values){
        Write-Output $ht2.Key   # <-- problem
    }
    

    Looks like a simple copy-paste error. You don't actually use the loop variable $testNames.

    A quick fix with the least changes to your existing code:

    foreach($testNames in $ht2.Values){
        Write-Output $testnames.PSObject.Properties.Name
    }
    

    I would simplify the code like this, though:

    # Iterate the top-level properties
    $changesJsonData.PSObject.Properties.ForEach{ 
        $_.Name                            # prints "testCases"
    
        # Iterate the child properties
        $_.Value.PSObject.Properties.Name  # prints "test-1" and "test-2"
    }
    

    Notes:

    • The code doesn't use Write-Output, because PowerShell implicitly outputs unassigned expressions, which is more succinct and faster.
    • The expression $_.Value.PSObject.Properties.Name relies on member access enumeration, which creates an array of all property names which is then implicitly output.