Итерирование с помощью имен ключей из PSCustomObject

Я пишу script для моего сайта, который использует файл конфигурации JSON. JSON похож на следующее:

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

Чтобы преобразовать объект в нечто, что может прочитать PowerShell, я использую ConvertFrom-Json, который преобразует его в тип PSCustomObject

Я нахожусь в точке, где мне нужно перебирать Groups и получить каждое имя группы для вывода их и их соответствующего индекса в объекте config Groups. То есть:.

1. GroupOne
2. GroupTwo
3. GroupThree

Самое дальнее, что я получил:

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

и все это выводит то, что выглядит как обозначение PS:

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

Возможно ли это с типом PSCustomObject? Я в первую очередь кодирую в JavaScript, поэтому, возможно, я упрощаю (или чрезмерную) проблему, поскольку это будет относительно легко.

Ответ 1

Я думаю, что, возможно, просто вычислил это благодаря следующему сайту:

http://blogs.msdn.com/b/timid/archive/2013/03/05/converting-pscustomobject-to-from-hashtables.aspx

Используя Get-Member, а затем -MemberType выставляет каждую группу, а затем вы просто тянете

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

Выходы:

GroupOne
GroupTwo
GroupThree

Я открыт для любых других методов.

Update

Итак, я нашел другой путь, но единственным недостатком является то, что он не использует причудливый ConvertFrom-Json CmdLet. Вместо этого он идет прямо в библиотеку .NET и использует его десериализатор и преобразует его в HashTable. Это полностью позволяет избежать путаницы с PSCustomObject. С hashtables IMO намного легче работать.

$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)"
}

Ответ 2

Решение

Я не уверен, как в начале версии вы можете это сделать, но это работает для меня в PowerShell 5.1... не стесняйтесь попробовать в более ранних версиях:

$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.
}

Выходы

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
--

Все это делается с помощью PowerShell 4.0; ConvertTo-Json и ConvertFrom-Json были представлены в PowerShell 3.0; Я не тестировал PowerShell 3.0 или 5.0.


Другой пример

Попробуйте это для себя с помощью другого примера:

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

Выходы

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
--

Этот и другие циклы PowerShell доступны в моем блоге.