如何使用Powershell从json属性获取键值对

the*_*ern 3 powershell

我被困在如何在事先不知道键值的情况下动态地从 json 文件中获取键值对。

我有这个示例 json 文件,在实际应用程序中,我有大约 20 个 json 文件和几千个自动化测试用例:

{
    "runOnMachines": "SERVER-01",
    "cases": [
    {
        "testName": "Google Chrome Install 84.0.4147.89",
        "testDescription": "Verifies Google Chrome is Installed 84.0.4147.89",
        "testFunction": "Find-ProgramVersion",
        "args": [
          {
            "programName" : "Firefox",
            "version"     : "79.0"
          }
        ],
        "expectedResult": "true"
      },
      {
        "testName": "Tera Term 4.105",
        "testDescription": "Tera Term 4.105",
        "testFunction": "Find-ProgramVersion",
        "args": [
          {
            "programName" : "Tera Term",
            "version"     : "4.105"     
          }
        ],
        "expectedResult": "true"
      }
    ]
}
Run Code Online (Sandbox Code Playgroud)

Find-ProgramVersion 是一个辅助函数,它搜索安装在控制面板中的程序/通过注册表安装的程序,它返回真或假。(有关此处的更多信息Winster是我为在服务器上测试虚拟机而构建的自动化框架的一部分。

长话短说,我有这个难看的代码,我正在尝试清理它,但我找不到如何从 json 文件中动态提取我的 args。到目前为止,我在 Winster 模块上编写的每个函数我都必须使用此脚本并使用正确的 json 属性手动添加它。

if($jsonData[$i].testFunction -eq "Find-ProgramVersion")
{
    $command = $jsonData[$i].testFunction + " " + $jsonData[$i].args.programName + " " + 
    $jsonData[$i].args.version
}

if($jsonData[$i].testFunction -eq "Find-ProgramVersionGrep")
{
    $command = $jsonData[$i].testFunction + " " + $jsonData[$i].args.programName + " " + 
    $jsonData[$i].args.version
}
Run Code Online (Sandbox Code Playgroud)

我试过转换jsonData[$i].args为数组,我也试过使用 PsObject.Properties 中的 Name 和 Value 但这也给出了我不需要从 PsObject 继承的其他值


for($i=0; $i -lt $jsonData.Count; $i++)
{ 
    $jsonData[$i].args.PSObject.Properties | ForEach-Object {
        $_.Name
        $_.Value
    }
}
Run Code Online (Sandbox Code Playgroud)

给我:

Count
1
Length
1
LongLength
1
Rank
1
SyncRoot

programName version
----------- -------
Firefox     79.0   
IsReadOnly
False
IsFixedSize
True
IsSynchronized
False
Count
1
Length
1
LongLength
1
Rank
1
SyncRoot
Tera Term   4.105  
IsReadOnly
False
IsFixedSize
True
IsSynchronized
False
Run Code Online (Sandbox Code Playgroud)

我希望从 jsonData[$i].args 得到某种可迭代的,在那里我可以使用 forloop,但我无法使下面的 PsObject 可用。并且无需事先知道 args 名称,因为某些函数具有不同数量的 args。

@{programName=Firefox; version=79.0} @{programName=Tera Term; version=4.105}
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 5

(@'
{
  "runOnMachines": "SERVER-01",
  "cases": [
  {
      "testName": "Google Chrome Install 84.0.4147.89",
      "testDescription": "Verifies Google Chrome is Installed 84.0.4147.89",
      "testFunction": "Find-ProgramVersion",
      "args": [
        {
          "programName" : "Firefox",
          "version"     : "79.0"
        }
      ],
      "expectedResult": "true"
    },
    {
      "testName": "Tera Term 4.105",
      "testDescription": "Tera Term 4.105",
      "testFunction": "Find-ProgramVersion",
      "args": [
        {
          "programName" : "Tera Term",
          "version"     : "4.105"     
        }
      ],
      "expectedResult": "true"
    }
  ]
}
'@ | ConvertFrom-Json).cases | ForEach-Object {
  $_.testFunction + ' ' + (
    $_.args.ForEach( { 
        $_.PSObject.Properties.Value.ForEach( {
            if ($_.contains(' ')) {
              # contains spaces -> double-quote
              '"{0}"' -f $_
            }
            else {
              $_
            }
          })
      })
  ) -join ' '
}
Run Code Online (Sandbox Code Playgroud)

以上返回以下内容:

(@'
{
  "runOnMachines": "SERVER-01",
  "cases": [
  {
      "testName": "Google Chrome Install 84.0.4147.89",
      "testDescription": "Verifies Google Chrome is Installed 84.0.4147.89",
      "testFunction": "Find-ProgramVersion",
      "args": [
        {
          "programName" : "Firefox",
          "version"     : "79.0"
        }
      ],
      "expectedResult": "true"
    },
    {
      "testName": "Tera Term 4.105",
      "testDescription": "Tera Term 4.105",
      "testFunction": "Find-ProgramVersion",
      "args": [
        {
          "programName" : "Tera Term",
          "version"     : "4.105"     
        }
      ],
      "expectedResult": "true"
    }
  ]
}
'@ | ConvertFrom-Json).cases | ForEach-Object {
  $_.testFunction + ' ' + (
    $_.args.ForEach( { 
        $_.PSObject.Properties.Value.ForEach( {
            if ($_.contains(' ')) {
              # contains spaces -> double-quote
              '"{0}"' -f $_
            }
            else {
              $_
            }
          })
      })
  ) -join ' '
}
Run Code Online (Sandbox Code Playgroud)

如果存在带有嵌入 "字符的值,则需要做更多的工作。

  • $_.args.ForEach遍历args数组的所有元素。

  • $_.PSObject.Properties.Value.ForEach 迭代每个元素的所有属性值。

  • $_.contains(' ')测试每个属性值是否存在至少一个空格字符,在这种情况下,该值在'"{0}"' -f $_正在构造的整个命令行中用双引号 ( )括起来(通过由空格连接的值构造的字符串和-join ' ')。