0

I have this JSON object, having nested level of "items" in powershell I want to iterate through all the objects using recursive function

[
    {
        "name":  "Introduction",
        "href":  "introduction.md"
    },
    {
        "name":  "Definitions and schema",
        "href":  "definition-and-schema/intro.md",
        "items":  [
            {
                "name":  "Entity definitions",
                "href":  "definition-and-schema/entity-definitions/intro.md",
                "items":  [
                    {
                        "name":  "Entity definitions page",
                        "href":  "definition-and-schema/entity-definitions/entity-definitions.md"
                    },
                    {
                        "name":  "Create a new Entity definition",
                        "href":  "definition-and-schema/entity-definitions/create-entity-definition.md"
                    },
                    {
                        "name":  "Member groups",
                        "href":  "definition-and-schema/entity-definitions/member-groups.md"
                    },
                    {
                        "name":  "Members",
                        "href":  "definition-and-schema/entity-definitions/members/intro.md",
                        "items":  [
                            {
                              "name":  "Adding a property",
                              "href":  "definition-and-schema/entity-definitions/members/adding-property.md"
                            },
                            {
                              "name":  "Adding a relation",
                              "href":  "definition-and-schema/entity-definitions/members/adding-relation.md"
                            },
                            {
                              "name":  "Adding a taxonomy",
                              "href":  "definition-and-schema/entity-definitions/members/adding-taxonomy.md"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

I am retrieving json object using ConvertFrom-Json

$jsonObject = ConvertFrom-Json $JsonString
iRon
  • 20,463
  • 10
  • 53
  • 79
Ayman Barhoum
  • 1,255
  • 1
  • 16
  • 31

2 Answers2

1

The following snippet recursively walks your object graph and processes each "items" property value:

$jsonObject | ForEach-Object {
    # Helper script block that walks the object graph.
    $sb = {
      foreach ($el in @($args[0])) { # iterate over elements (if an array)
        foreach ($prop in $el.psobject.Properties) { # iterate over properties
          if ($prop.Name -eq 'items') {
            # Process the "items" property value here (may be an array)
            $prop.Value 
          }
          & $sb $prop.Value  # recurse
        }
      }
    }
    # Call the script block with the input object.
    & $sb $_
  }
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

A common reusable function to recursively find (and/or replace) a node in a PowerShell object:

function Get-Node {
  [CmdletBinding()][OutputType([Object[]])] param(
    [ScriptBlock]$Where,
    [AllowNull()][Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
    [Int]$Depth = 10
  )
  process {
    if ($_ -isnot [String] -and $Depth -gt 0) {
      if ($_ -is [Collections.IDictionary]) {
        if (& $Where) { $_ }
        $_.get_Values() | Get-Node -Where $Where -Depth ($Depth - 1)
      }
      elseif ($_ -is [Collections.IEnumerable]) {
        for ($i = 0; $i -lt $_.get_Count(); $i++) { $_[$i] | Get-Node -Where $Where -Depth ($Depth - 1) }
      }
      elseif ($Nodes = $_.PSObject.Properties.Where{ $_.MemberType -eq 'NoteProperty' }) {
        $Nodes.ForEach{
          if (& $Where) { $_ }
          $_.Value | Get-Node -Where $Where -Depth ($Depth - 1)
        }
      }
    }
  }
}

Usage

Finding the value of specific nodes:

($jsonObject |Get-Node -Where { $_.name -eq 'Name' -and $_.value -Like '*Member*' }).Value

Member groups
Members

In case of a hashtable:

$HashTable = ConvertFrom-Json $JsonString -AsHashTable
($HashTable |Get-Node -Where { $_.name -Like '*Member*' }).href

Warning: unlike PowerShell normal behavior, the hashtable kays are case sensitive.
See also: #14143 JSON auto-parse is case insensitive

Replacing all values of a specific node:

$jsonObject |Get-Node -Where { $_.Name -eq 'href' } |
    ForEach-Object { $_.Value  = 'href://' + $_.Value }
$JsonObject |ConvertTo-Json -Depth 9

Results

[
  {
"name": "Introduction",
"href": "href://introduction.md"
  },
  {
"name": "Definitions and schema",
"href": "href://definition-and-schema/intro.md",
"items": [
  {
    "name": "Entity definitions",
    "href": "href://definition-and-schema/entity-definitions/intro.md",
    "items": [
      {
        "name": "Entity definitions page",
        "href": "href://definition-and-schema/entity-definitions/entity-definitions.md"
      },
      {
        "name": "Create a new Entity definition",
        "href": "href://definition-and-schema/entity-definitions/create-entity-definition.md"
      },
      {
        "name": "Member groups",
        "href": "href://definition-and-schema/entity-definitions/member-groups.md"
      },
      {
        "name": "Members",
        "href": "href://definition-and-schema/entity-definitions/members/intro.md",
        "items": [
          {
            "name": "Adding a property",
            "href": "href://definition-and-schema/entity-definitions/members/adding-property.md"
          },
          {
            "name": "Adding a relation",
            "href": "href://definition-and-schema/entity-definitions/members/adding-relation.md"
          },
          {
            "name": "Adding a taxonomy",
            "href": "href://definition-and-schema/entity-definitions/members/adding-taxonomy.md"
          }
        ]
      }
    ]
  }
]
  }
]
iRon
  • 20,463
  • 10
  • 53
  • 79