如何从Powershell中的JSON值获取值

时间:2019-09-16 12:38:11

标签: json powershell

我有一个json文件

{
"value":  [
              {
                  "applicationVersion":  "@{major=14; minor=5; build=35970; revision=0; majorRevision=0; minorRevision=0}",
                  "ringName":  "PROD",
                  "ringFriendlyName":  "Production"
              },
              {
                  "applicationVersion":  "@{major=15; minor=0; build=35903; revision=0; majorRevision=0; minorRevision=0}",
                  "ringName":  "PREVIEW",
                  "ringFriendlyName":  "Preview"
              }
          ]
}

我想从ringName = Preview获取主要,次要,内部版本和修订版值。

我尝试过

$supportedVersions = $myJson | ConvertFrom-Json
$appVersion = $supportedVersions.value | where { $_.ringFriendlyName -eq "Preview" } | Select -ExpandProperty "applicationVersion" 

这让我回来

@{major=15; minor=0; build=35903; revision=0; majorRevision=0; minorRevision=0}

但是当我尝试

    $major = $appVersion | select major

它什么也没给我

enter image description here

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:0)

如果保留数据不变,则可以将输出字符串作为脚本调用。这将产生一个具有可引用属性的哈希表。

$appVersion = $supportedVersions.value |
    Where-Object { $_.ringFriendlyName -eq "Preview" } |
        Select-Object -ExpandProperty "applicationVersion") | Invoke-Expression

$appVersion.Major
15

正如mclayton所指出的那样,这将不是首选方法。 Invoke-Expression通常被认为是“不良”或“邪恶”的,因为恶意代码很容易在不知不觉中被执行。您必须信任提供数据的来源。

答案 1 :(得分:0)

您的JSON数据中的字段applicationVersion的值是一个字符串。从外观上看,JSON是通过ConvertTo-Json创建的,没有指定转换深度。默认情况下,ConvertTo-Json将层次结构第二级以下的所有子结构转换为字符串。

解决您问题的最佳方法是通过向-Depth调用中添加值> 2的参数ConvertTo-Json来修复JSON导出,例如

... | ConvertTo-Json -Depth 10 | ...

如果无法执行此操作,则需要从字符串中解析出所需的信息,例如带有正则表达式:

$appVersion |
    Select-String '(?<=major=)\d+' |
    Select-Object -Expand Matches |
    Select-Object -Expand Value

涉及脚本块的更具创意的方法可能看起来像这样:

$appVersion | ForEach-Object {
    (& ([Scriptblock]::Create($_))).major
}

但是请注意,我实际上不建议使用后一种方法。

答案 2 :(得分:0)

对于您的示例来说,这可能是多余的,但是要安全将任意PowerShell表达式转换为值,您可以使用内置的PowerShell解析器。下面的代码适用于哈希表...

function ConvertTo-HashTable
{
    param( [string] $PsCode )
    $tokens = $null;
    $errors = $null;
    $scriptBlockAst = [System.Management.Automation.Language.Parser]::ParseInput($PsCode, [ref] $tokens, [ref] $errors);
    if( $errors.Length -gt 0 )
    {
        throw "Invalid powershell script - errors are:`r`n$errors";
    }
    $hashtableAst = $scriptBlockAst.EndBlock.Statements[0].PipelineElements[0].Expression;
    if( ($null -eq $hashtableAst) -or
        -not ($hashtableAst -is [System.Management.Automation.Language.HashTableAst]) )
    {
        throw "couldn't find a hashtable in the script";
    }
    return $hashtableAst.SafeGetValue();
}

示例:

PS> ConvertTo-Hashtable "@{`"major`" = 15}"

Name                           Value
----                           -----
major                          15

请注意,如果字符串中包含任何表达式,它将引发异常,从而保护您免受PowerShell注入攻击:

PS> ConvertTo-Hashtable "@{`"major`" = 1 + 1}"
Exception calling "SafeGetValue" with "0" argument(s): "Cannot generate a Windows PowerShell object for a ScriptBlock
evaluating dynamic expressions. Dynamic expression: @{"major" = 1 + 1}."
At line:17 char:12
+     return $hashtableAst.SafeGetValue();
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidOperationException
PS> ConvertTo-Hashtable "@{`"major`" = (Format-Volume -DriveLetter X)}"
Exception calling "SafeGetValue" with "0" argument(s): "Cannot generate a Windows PowerShell object for a ScriptBlock
evaluating dynamic expressions. Dynamic expression: @{"major" = (Format-Volume -DriveLetter X)}."
At line:17 char:12
+     return $hashtableAst.SafeGetValue();
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidOperationException