1

After opening a .json file in PowerShell, I've got a new PSObject called $json_sitesandsnets. Ultimately what I want to do is loop through each Site (Orlando, Denver), and loop through each of their subnets, and do stuff. Initially, I need to create these subnets for the corresponding Site in Active Directory with the New-ADReplicationSubnet cmdlet. I've already used this to create a single subnet, but I've got a much larger list of Sites & Subnets I'll be working with. This example is just a small trimmed down version to post here. Once I figure out how to access those subnets in the objects Value, I might just feed each subnet list to New-ADReplicationSubnet. But I really want to be able to loop through each subnet for other purposes. I'm thinking that this is probably not difficult to do, once you know how to do it.

Here is the raw json:

{
"Orlando":  [
                        "10.10.10.0/24",
                        "10.10.20.0/24",
                        "10.10.30.0/24",
                        "10.10.40.0/24"
                    ],
"Denver":  [
                       "10.0.70.0/24",
                       "10.0.80.0/24",
                       "10.0.90.0/24",
                       "10.0.100.0/24",
                       "10.0.110.0/24",
                       "10.0.120.0/24"
                   ]
}

And I get the PSObject's properties like this:

$json_sitesandsnets.psobject.properties

PSObject properties

When I run Debug in VSCode, I can see the PSObject and the list (array) of subnets: seeing this in Debug

Here is some code, which gets the Name no problem (Write-Host $site.Name). As you can see, I've tried a couple of different ways to access those subnets, which are the Value of each site. And I just cannot figure it out. I've read so many articles and forum threads about looping through PSObjects, but just can't seem to find the golden answer to accessing and looping through the array that is the Value of the PSObject. I feel like I'm really close.

foreach ($site in $json_sitesandsnets.PSObject.Properties) {
Write-Host $site.Name
$site| get-member -type NoteProperty | foreach-object {
    $subnet = $site."$($_.Value)"
    Write-Host $subnet
    Write-Host $_.Value
}
}
js2010
  • 23,033
  • 6
  • 64
  • 66
stackDram
  • 13
  • 1
  • 4
  • What happens if you do (inside the loop) a $site.Value | gm – Walter Mitty Dec 28 '19 at 22:23
  • $site.value is definitely where I need to go with this. – stackDram Dec 29 '19 at 17:33
  • I'm too lazy to set up your case on my computer. But I expect that $site.value is some kind of container with a list, an array or something composed of IP addresses. You'll then need to write an inner loop to pick those up one at a time and format them. – Walter Mitty Dec 29 '19 at 20:06

3 Answers3

0

You can do this by using the site name to index. $json_sitesandsnets.($site.Name)

I would also use $json_sitesandsnets.PSObject.Properties.Name in the foreach instead of $json_sitesandsnets.PSObject.Properties, to simplify things:

foreach ($site in $json_sitesandsnets.PSObject.Properties.Name) {
    Write-Host $site
    foreach ($subnet in $json_sitesandsnets.$site){
        Write-Host "logic for subnet $subnet"
    }
    # alternatively
    $json_sitesandsnets.$site | ForEach-Object {
        Write-Host "logic for subnet $_ (foreach-object)"
    }
}

Edit: Your approach wasn't working because the subnets are a string array and the subnets are not named properties/noteproperties. You can see this by doing the following.

# This tells you it's an array of "objects" with properties Length, Rank etc
Get-Member -InputObject $json_sitesandsnets.Denver

# This pipes the array elements, telling you they are strings with Length property
# In powershell strings are an object that only have properties Chars/Length
$json_sitesandsnets.Denver | Get-Member

# To only return the types
$json_sitesandsnets.Denver.GetType()
$json_sitesandsnets.Denver[0].GetType()
G42
  • 9,791
  • 2
  • 19
  • 34
0

It looks like to me that what you want is this.

foreach ($site in $json_sitesandsnets.PSObject.Properties) {
    Write-Host $site.Name -ForegroundColor Cyan
    $site.Value | Out-String | Write-Host 
}

Output

Output #1

For the subnet values, the not properties are Orlando and Denver. You got that part right however your $site| get-member line shouldn't be there. Instead, you can access the value through $site.value directly. If you needto do something more, you can loop through these values, like this:

$index = 0
Foreach ($subnet in $site.Value) {
    Write-Host "$($index): $subnet"
    $index+=1
}

Output

Output #2

Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39
  • I believe this is going to be what I need. After posting this yesterday, I was reviewing it, and it occurred to me that Site.Value should give me those subnets. Then I saw your post and it was confirmed. – stackDram Dec 29 '19 at 17:31
  • can you help me understand why we would need the indexing? The .Value (the subnets) already appears to be an array as (see Debug screenshot). I was able to loop through these subnets like this: foreach ($site in $json_sitesandsnets.PSObject.Properties) { Write-Host $site.Name -ForegroundColor Cyan foreach ($subnet in $site.Value) { Write-Host $subnet } } – stackDram Dec 29 '19 at 17:40
  • `foreach ($site in $json_sitesandsnets.PSObject.Properties) { Write-Host $site.Name -ForegroundColor Cyan foreach ($subnet in $site.Value) { Write-Host $subnet } }` – stackDram Dec 29 '19 at 17:50
  • @stackDram You absolutely do not need to index anything. This bit was just to demonstrate a basic loop iterating through all the subnet sine in my main example, I bypassed the Foreach using `$site.Value | Out-String | Write-Host ` – Sage Pourpre Dec 29 '19 at 19:38
0

I don't suppose the json could be like this? The resulting object array in powershell would be easier to work with. It could almost be a csv.

[
  {
    "site": "Orlando",
    "subnets": [
      "10.10.10.0/24",
      "10.10.20.0/24",
      "10.10.30.0/24",
      "10.10.40.0/24"
    ]
  },
  {
    "site": "Denver",
    "subnets": [
      "10.0.70.0/24",
      "10.0.80.0/24",
      "10.0.90.0/24",
      "10.0.100.0/24"
    ]
  }
]


cat sites.json | convertfrom-json     

site    subnets
----    -------
Orlando {10.10.10.0/24, 10.10.20.0/24, 10.10.30.0/24, 10.10.40.0/24}
Denver  {10.0.70.0/24, 10.0.80.0/24, 10.0.90.0/24, 10.0.100.0/24}
js2010
  • 23,033
  • 6
  • 64
  • 66