2

I have a json file, simplified version of it looks like this:

 {
  "Location": "EU",
  "Country": {
    "City": "xxx",
    "Town": "xxx"
  },
  "Transport": {
    "Train": "xxx"
  }
}

I have run the ConvertFrom-Json command to convert to PSObject:

$conversion = Get-Content $path | ConvertFrom-Json 

This will give me an output like this:

Location                           : EU
Country                            : @{City="xxx"; Town="xxx"}
Transport                          : @{Train="xxx"}

Question

How can I get the nested values to print out separately? I would want them all to print out like the "Location:EU" one

Is there a different command to ConvertFrom-Json that i should be using for this? Or do I just need to mess around with ConvertFrom-Json command a bit?

To note:

  • I am not just looking for a pretty print out - I would need them all separately for a script I am writing that will be looping through all the key/value pairs
  • I have read about the -Depth flag when using ConvertFrom-Json and does not seem to fix anything here - it seemed this was more relevant for ConvertTo-Json
3
  • I think the way you have it will work fine, that output is just how powershell displays the nesting. For example if you do $conversion.Country.City you will just get xxx out. Commented Oct 18, 2022 at 13:15
  • @frankM_DN thanks for replying! strange - that doesn't work for me. It returns nothing Commented Oct 18, 2022 at 13:38
  • hmm. I just copied the text that you say is in the json file into a string variable and it worked for me. So maybe something wonky with the json file? I put that text into a file and used get-content | convertfrom-json and that worked as well. Commented Oct 18, 2022 at 13:46

1 Answer 1

2

In order to report all leaf properties as name-value pairs (i.e. those properties that contain primitive JSON values as opposed to containing nested objects with properties and / or arrays), you need to recursively walk the object graph:

Find helper function Get-LeafProperty below; assuming you have already defined it, you can call it as follows:

@'
  {
    "Location": "EU",
    "Country": {
      "City": "xxx",
      "Town": "xxy"
    },
    "Transport": {
      "Train": "xxz"
    }
  }
'@ | 
  ConvertFrom-Json |
  Get-LeafProperty

Output (the display formatting of [pscustomobject] instances with .Name and .Value properties representing all the leaf properties):

Name     Value
----     -----
Location EU
City     xxx
Town     xxy
Train    xxz

Get-LeafProperty source code:

# Walks a potentially nested [pscustomobject] graph
# as returned by ConvertFrom-Json and outputs all
# leaf properties as name-value custom objects.
function Get-LeafProperty {
  param([Parameter(ValueFromPipeline)] [object] $InputObject)
  process {   
    if ($InputObject -is [array]) { # array as single input object -> recurse
      foreach ($o in $InputObject) { Get-LeafProperty $o }
    }
    else { 
      # Assumed to be a (potentially nested) [pscustomobject] instance:
      # Recursively process its properties.
      foreach ($p in $InputObject.psobject.properties) {
        if ($p.Value -is [array]) { # array -> recurse
          foreach ($o in $p.Value) { Get-LeafProperty $o }
        } elseif ($p.Value -is [System.Management.Automation.PSCustomObject] ) { # nested [pscustomobject] -> recurse
          Get-LeafProperty $p.Value
        } else { # leaf property reached -> output name-value pair
          [pscustomobject] @{ Name = $p.Name; Value = $p.Value }
        }
      }
    }
  }
}

Note: A variant of this function that outputs property name paths (e.g. Country.City) instead of just their names (e.g. City) can be found in this answer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.