如何在PowerShell中遍历JSON数组

时间:2018-02-15 23:14:58

标签: powershell

如何迭代使用PSCustomObject转换为ConvertFrom-JSON的JSON数组?使用foreach不起作用。

$jsonArray ='[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
$json = convertfrom-json $jsonArray
$json | foreach {$_}

返回

privateKeyLocation
------------------
C:\ProgramData\docker\certs.d\key.pem

枚举器虽然说有3个数组成员

>$json.Count
3

5 个答案:

答案 0 :(得分:2)

您遇到的问题并非特定于它是一个JSON数组,它与默认情况下显示数组中自定义对象的方式有关。最简单的答案是将其传递给Format-List(或简称为FL)。

PS C:\Users\TMTech> $JSON|FL


privateKeyLocation : C:\ProgramData\docker\certs.d\key.pem

publicKeyLocation : C:\ProgramData\docker\certs.d\cert.pem

publicKeyCALocation : C:\ProgramData\docker\certs.d\ca.pem

除此之外,当PowerShell输出一个对象数组时,它将显示的列基于数组中第一个对象的属性。在您的情况下,该对象具有一个名为“privateKeyLocation”的属性,因此这是唯一出现的列,并且由于其他两个对象没有该属性,因此它不会显示任何内容。如果你想把它保存为一个表,你可以收集所有潜在的属性,并将它们添加到具有空值的第一个项目,这将允许你将它显示为一个表,但它仍然看起来不太好:< / p>

$json|%{$_.psobject.properties.name}|select -Unique|?{$_ -notin $json[0].psobject.Properties.Name}|%{Add-Member -InputObject $JSON[0] -NotePropertyName $_ -NotePropertyValue $null}

然后你可以输出一个表并获得所有东西:

PS C:\Users\TMTech> $json

privateKeyLocation                    publicKeyLocation                      publicKeyCALocation                 
------------------                    -----------------                      -------------------                 
C:\ProgramData\docker\certs.d\key.pem                                                                            
                                      C:\ProgramData\docker\certs.d\cert.pem                                     
                                                                             C:\ProgramData\docker\certs.d\ca.pem

编辑:在这种情况下获取每个对象的值很棘手,因为要扩展的属性会不断更改每个对象。有两种方法可以做到这一点,我能想到的是,我认为正确的方式,然后是简单的方法。正确的方法是确定要扩展的属性,然后直接引用该属性:

$JSON |%{
    $PropName = $_.PSObject.Properties.Name
    $_.$PropName
}

那会做你想要的,但我认为更容易管道到Format-List,然后Out-String,将整个事物包裹在括号中,拆分新行并将所有内容替换为{ {1}}应该只留下你想要的路径。

:

答案 1 :(得分:1)

足够有趣。我在另一个论坛上从同一个OP回复了这个确切的问题。虽然我的回答只是RegEx并且已完成,但没有额外的转换。

Of course there are several ways to do this. The below is just what I came up with.
$jsonArray = '[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'

([regex]::Matches($jsonArray,'(?<=\").:\\[^\"]+(?=\")').Value) -replace '\\\\','\' `
| ForEach { 
            If (Test-Path -Path $_)
            {"path $_ found"}
            Else {Write-Warning "Path $_ not found"}
            }


WARNING: Path C:\ProgramData\docker\certs.d\key.pem not found
WARNING: Path C:\ProgramData\docker\certs.d\cert.pem not found
WARNING: Path C:\ProgramData\docker\certs.d\ca.pem not found

所以,也许不像这里发布的那样优雅,但它会让OP成为他们想要的地方。

因此,巩固TheMadTechnician提供的所有内容以及OP所追求的内容,并尽量使其尽可能简洁,将给OP提供以下内容(我添加了一个元素以显示正面响应):

Clear-Host 
($jsonArray = @'
[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"},
{"publicKeyTestFileLocation" : "D:\\Temp\\test.txt"}]
'@ | ConvertFrom-Json | Format-List | Out-String) -split '[\r\n]+' -replace '(?m)^.+ : '`
| Where-Object {$_} | ForEach {
    If(Test-Path -Path $_){"The path $_ was found"}
    Else{Write-Warning -Message "The path $_ was not found}"}
}

WARNING: The path C:\ProgramData\docker\certs.d\key.pem was not found}
WARNING: The path C:\ProgramData\docker\certs.d\cert.pem was not found}
WARNING: The path C:\ProgramData\docker\certs.d\ca.pem was not found}
The path D:\Temp\test.txt was found

哪一个更符合他的喜好,当然是选择OP的问题。

两次测试之间的性能各不相同,但使用直接RegEx方法的最快时间是:

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 43
Ticks             : 439652
TotalDays         : 5.08856481481481E-07
TotalHours        : 1.22125555555556E-05
TotalMinutes      : 0.000732753333333333
TotalSeconds      : 0.0439652
TotalMilliseconds : 43.9652

并且合并版本中最快的是:

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 54
Ticks             : 547810
TotalDays         : 6.34039351851852E-07
TotalHours        : 1.52169444444444E-05
TotalMinutes      : 0.000913016666666667
TotalSeconds      : 0.054781
TotalMilliseconds : 54.781

更新以添加iRon对此主题的看法

所以这......

$jsonArray ='[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
$json = convertfrom-json $jsonArray

$json | ForEach {
    $Key = $_.psobject.properties.name; 
    "Testing for key " + $_.$Key
    Test-Path -Path $_.$Key
} 


Testing for key C:\ProgramData\docker\certs.d\key.pem
False
Testing for key C:\ProgramData\docker\certs.d\cert.pem
False
Testing for key C:\ProgramData\docker\certs.d\ca.pem
False

......而且这个:

('[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]' `
| convertfrom-json) | ForEach {
    $Key = $_.psobject.properties.name; 
    "Testing for key " + $_.$Key
    Test-Path -Path $_.$Key
} 

Testing for key C:\ProgramData\docker\certs.d\key.pem
False
Testing for key C:\ProgramData\docker\certs.d\cert.pem
False
Testing for key C:\ProgramData\docker\certs.d\ca.pem
False

答案 2 :(得分:0)

您可以索引到数组。查看 <input class="form-radio" type="radio" name="attribute[12175]" value="1061" id="attribute_1061" required> <label class="form-option form-option-swatch" for="attribute_1061" data-product-attribute-value="1061"> <span class='form-option-variant form-option-variant--color tooltip' title="Graphite (PMS Black 7)" style="background-color: #4E4B49"></span> </label>

$json.GetType()

答案 3 :(得分:0)

最简单的方法应该是这样



            'exclude_cats'              => '',
            'layout'                    => 'large',
            'meta_all'                  => 'yes',
            'meta_author'               => 'yes',
            'meta_categories'           => 'yes',
            'meta_comments'             => 'yes',
            'meta_date'                 => 'yes',
            'meta_link'                 => 'yes',
            'meta_read'                 => 'yes',
            'meta_tags'                 => 'no',
            'number_posts'              => '6',
            'offset'                    => '',
            'order'                     => 'DESC',
            'orderby'                   => 'date',
            'paging'                    => 'yes',
            'show_title'                => 'yes',
            'scrolling'                 => 'infinite',
            'strip_html'                => 'yes',
            'thumbnail'                 => 'yes',
            'title_link'                => 'yes',
            'posts_per_page'            => '6',
            'taxonomy'                  => 'category',

            'excerpt_words'             => '50',    //deprecated
            'title'                     => '',  // deprecated               
        ), $args
    );

答案 4 :(得分:0)

您可以使用ForEach-Object,即:

$json | ForEach-Object -Process { Write-Hoste $_; }

我相信这是最简单的方法,如果数组包含具有其他属性的对象,则可以轻松访问属性。