Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating through key names from a PSCustomObject

I am writing a script for my site that utilizes a JSON configuration file. The JSON is similar to the following:

"Groups": {
    "GroupOne": {
        "NamingFilter": {
            "Not":"<SITE>-MJ*",
            "Has":"*WM,*WT"
        }
    },
    "GroupTwo": {
        "NamingFilter": {
            "Has":"<SITE>-MJ*, *WC,*WL"
        }
    },
    "GroupThree": {
        "NamingFilter": {
            "Not":"<SITE>-MJ*",
            "Has":"*WI"
        }
    }
}

To convert the object to something PowerShell can read, I use ConvertFrom-Json which converts it to type PSCustomObject.

I am at a point where I have to iterate over the Groups and get each group name to output them and their corresponding index within the configuration's Groups object. That is,

1. GroupOne
2. GroupTwo
3. GroupThree

The furthest I have gotten is:

foreach ($group in $configObject.Groups) {
    $group
}

And all this does is output something that looks like PowerShell array notation:

@{GroupOne=; GroupTwo=; GroupThree=;}

Is this even possible with a PSCustomObject type? I primarily code in JavaScript so perhaps I am oversimplifying (or overcomplicating it) the issue since this would be relatively easy.

like image 727
SomeShinyObject Avatar asked Sep 13 '13 06:09

SomeShinyObject


2 Answers

Solution

I'm not sure how early of a version you can do this with, but it works for me in PowerShell 5.1... Feel free to give it a try in earlier versions:

$ipinfo = Invoke-WebRequest 'http://ipinfo.io/json' -UseBasicParsing | ConvertFrom-Json
foreach ($info in $ipinfo.PSObject.Properties) {
    $info.Name
    $info.Value
    '--' # <-- Seeing this double hash proves we're iterating fully.
}

Outputs

ip
1.2.3.4
--
hostname
No Hostname
--
city
Denton
--
region
Texas
--
country
US
--
loc
33.2148,-97.1331
--
org
AS589 University of North Texas
--
postal
76203
--

This is all done with PowerShell 4.0; ConvertTo-Json and ConvertFrom-Json were introduced in PowerShell 3.0; I haven't tested PowerShell 3.0 or 5.0.


Another Example

Try it for yourself with another example:

$ipinfo = ConvertFrom-Json (Invoke-WebRequest 'http://ipinfo.io/json' -UseBasicParsing)
foreach ($info in ($ipinfo.PSObject.Members | ?{ $_.MemberType -eq 'NoteProperty'})) {
    $info.Name
    $info.Value
    '--'
}

Outputs

ip
1.2.3.4
--
hostname
No Hostname
--
city
Denton
--
region
Texas
--
country
US
--
loc
33.2148,-97.1331
--
org
AS589 University of North Texas
--
postal
76203
--

This and other PowerShell looping are available on my blog.

like image 70
VertigoRay Avatar answered Sep 27 '22 20:09

VertigoRay


I think I might have just figured it out thanks to the blog post Converting PsCustomObject To/From Hashtables.

Using Get-Member and then -MemberType exposes each Group and then you just pull the:

foreach ($group in $configObject.Groups) {
    $groupName = $($group | Get-Member -MemberType *Property).Name
}

Outputs:

GroupOne
GroupTwo
GroupThree

I'm open to any other methods though.

Update

I've found another way, but the only drawback is it doesn't use the fancy ConvertFrom-Json CmdLet. Instead it goes straight to the .NET library and uses its deserializer and converts it to a HashTable. This completely avoids having to muddle around with the PSCustomObject. IMO hashtables are a whole lot easier to work with.

$JSON = Get-Content -Path path/to.json -Raw
$HT = (New-Object System.Web.Script.Serialization.JavaScriptSerializer).Deserialize($JSON, [System.Collections.Hashtable])
$HT.Groups.GetEnumerator() | ForEach-Object {
    Write-Host "$($_.Key) : $($_.Value)"
}
like image 22
SomeShinyObject Avatar answered Sep 27 '22 22:09

SomeShinyObject