使用 Powershell 从 JSON 中获取值

3

非常初级的问题。我正在尝试使用PowerShell从JSON获取特定的值。具体来说,我想列出以下服务:TEST00000FAKE

当我运行下面的脚本时,我得到了这个结果:

TEST00000                                                    FAKE           
---------                                                    ----           
@{Enabled=True; Processed=2; Sent=3; Failed=4; Downloaded=5} @{Enabled=True}

如何获取仅包含服务的列表?

更重要的是,如何列出仅包含具有键/值Enabled=True的服务的列表?

以下是代码:

$JSON = '{
  "Envs": {
    "DEV": {
      "Services": {
        "TEST00000": {
          "Enabled": true,
          "Processed": 2,
          "Sent": 3,
          "Failed": 4,
          "Downloaded": 5
        },
        "FAKE": {
          "Enabled": true
        }
      }
    }
  },
  "Component": {
    "Digger": {
      "Envs": {
        "DEV": {
          "DownloadE": 4
        }
      }
    }
  }
}'

$jsonobj = ConvertFrom-Json -inputObject $JSON

$jsonobj.Envs.DEV.Services
2个回答

4
为了获取每个“服务”属性的名称,您可以像user2734259一样使用“Get-Member”,也可以使用“psobject”属性,该属性存储有关对象的有用信息。
$ServiceNames = $jsonobj.Envs.DEV.Services.psobject.properties.name

一旦您有了名称,就可以对它们进行循环,并过滤子属性Enabled

$jsonobj.Envs.DEV.Services.psobject.properties.name | ForEach-Object { 
    $_ | Where-Object {$jsonobj.Envs.DEV.Services.$_.Enabled -eq $True}
}

非常感谢您的回复,这真的很有趣。我花了很多时间寻找这些信息,你们是怎么学到的呢?我在哪里可以进一步阅读相关内容?(或者是学习如何使用PS帮助文档的艺术!?) - ToastMan
1
@ToastMan 我个人是从Don Jones的“Month of Lunches”系列书籍开始学习的。我从Stack Overflow上某个人的答案中了解到了隐藏的psobject属性(已经太久了,记不清是谁了)。 - BenH
最后一部分似乎不起作用:$_ | Where-Object {$jsonobj.Envs.DEV.Services.$_.Enabled -eq 'false'} <-- 无论如何都会列出服务(带有-eq 'false')。 - ToastMan
@ToastMan 更新了我的答案以解决这个问题。这是因为 Enabled 属性是一个布尔值。当你尝试将字符串 'false' 转换为布尔值时,它会变成 $True。你可以用 [bool]'false' 进行测试。 - BenH

1
这样做可以让你动态获取名称,无论JSON中的服务名称是什么:
$JSON = '{
  "Envs": {
    "DEV": {
      "Services": {
        "TEST00000": {
          "Enabled": true,
          "Processed": 2,
          "Sent": 3,
          "Failed": 4,
          "Downloaded": 5
        },
        "FAKE": {
          "Enabled": true
        }
      }
    }
  },
  "Component": {
    "Digger": {
      "Envs": {
        "DEV": {
          "DownloadE": 4
        }
      }
    }
  }
}'

$jsonobj = ConvertFrom-Json -inputObject $JSON
$enabledServices = $NULL
$disabledServices = $NULL

# Since the service names are arbitrary
# create an object that contains only
# objects whose MemberType is NoteProperty

$strServiceNames = @($($jsonobj.Envs.DEV.Services | Get-Member | Where { $_.MemberType -eq "NoteProperty" } | Select Name).Name)
$pscoServiceNames = [PSCustomObject]@{Names=$strServiceNames}
foreach($serviceName in $pscoserviceNames.Names)
{
    # dynamically access the service name
    # from $jsonobj.Envs.DEV.Services

    $serviceStatus = $jsonobj.Envs.DEV.Services.$serviceName.Enabled

    # parse results based on value of .Enabled

    if($serviceStatus.ToString() -eq "True")
    {
        $enabledServices = [Array]$enabledServices + [PSCustomObject]@{Name = $serviceName;Enabled = $serviceStatus}
    }
    else
    {
        $disabledServices = [Array]$disabledServices + [PSCustomObject]@{Name = $serviceName;Enabled = $serviceStatus}
    }
}

# Show the results

Write-Output "`nEnabled Services`n"
$enabledServices | Format-List
Write-Output "`nDisabled Services`n"
$disabledServices | Format-List

如果有任何不清楚的地方,请让我知道,我可以更详细地解释。希望这能帮助你。祝你玩得开心!

非常感谢您的回复,这真是太有趣了! - ToastMan
如果($serviceStatus -eq "False") <-- 给我完全相同的结果: 已启用的服务名称:FAKE 已启用:是名称:TEST00000 已启用:是 - ToastMan
@toastman 我会在回到编写代码的机器时重新访问并进行必要的修复,并为完整起见编辑我的答案。我认为这可能是一个类型问题,但会进行检查。在此期间,祝你节日快乐。 - trebleCode
是的,这是一个类型错误。$serviceStatus 是布尔类型,因此需要将其转换为字符串以匹配正则表达式。所以只需将那一行更改为:if($serviceStatus.ToString() -eq "False"),它应该按预期工作。 - trebleCode
非常感谢trebleCode。最终我将BenH的回答标记为解决方案,因为我最终使用了他的代码。但是我非常感谢你的帮助。 - ToastMan
没问题,随时乐意帮忙。 - trebleCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接