【问题标题】:Powershell Selecting NoteProperty Type Objects From ObjectPowershell 从对象中选择 NoteProperty 类型对象
【发布时间】:2020-10-03 17:26:12
【问题描述】:

我正在使用深度嵌套的 JSON,并且在 convertfrom-json 之后,需要能够遍历 convertfrom-json cmdlet 生成的对象的各个部分。

我无法提前知道对象内部可能包含或不包含哪些属性名称,据我所知,有数百种不同的可能属性。幸运的是,我看到的有帮助的一件事是,我关心的每个属性都是“NoteProperty”类型。

这是一个例子:

TypeName: System.Management.Automation.PSCustomObject

Name               MemberType   Definition
----               ----------   ----------
Equals             Method       bool Equals(System.Object obj)
GetHashCode        Method       int GetHashCode()
GetType            Method       type GetType()
ToString           Method       string ToString()
definition         NoteProperty System.Management.Automation.PSCustomObject definition=@{$schema=https://schema.management.azure.com/providers/Microsof... 
integrationAccount NoteProperty System.Management.Automation.PSCustomObject integrationAccount=@{id=[parameters('integrationAccounts_xxx_integration... 
parameters         NoteProperty System.Management.Automation.PSCustomObject parameters=@{$connections=}
state              NoteProperty string state=Enabled

所以我认为创建一个只选择对象的函数会很简单,对于当前正在处理的级别,它们是'MemberType''NoteProperty'。

我已尝试将对象通过管道传输到:

where-object { $_.MemberType -eq "NoteProperty" }

没有。

我也尝试过各种形式的选择对象,但似乎无法选择我需要的东西。我从脚本专家那里找到了一篇关于使用标签和表达式的旧文章——但这似乎有点矫枉过正,不是吗?有人可以指出我只选择 NoteProperty 项目的简单方法吗?

谢谢!

【问题讨论】:

  • 看看大多数powershell对象的隐藏.PSObject属性。它包含一个名为.Properties 的属性,它将为您提供对象的所有道具......并且您可以遍历它们。如果您需要深入研究子属性,那么您可能会发现在原始 JSON 上使用正则表达式更容易... [sigh ...]
  • 另一种方法是使用 Get-Member -MemberType NoteProperty 来获取属性名称。不过,我认为 PSObject.Properties 更有意义。
  • @Lee_Dailey 非常感谢!是的,这是一个很好的解决方案,感谢您的建议,我重新启动并运行。谢谢!
  • @Indrid - 酷!很高兴能帮上一点忙……[grin]

标签: powershell pscustomobject


【解决方案1】:

您可以使用隐藏的.psobject.properties 来遍历成员。

$json = @'
{
  "users": [
    {
      "userId": 1,
      "firstName": "Krish",
      "lastName": "Lee",
      "phoneNumber": "123456",
      "emailAddress": "krish.lee@learningcontainer.com"
    },
    {
      "userId": 2,
      "firstName": "racks",
      "lastName": "jacson",
      "phoneNumber": "123456",
      "emailAddress": "racks.jacson@learningcontainer.com"
    }
  ]
}
'@ | ConvertFrom-Json

$json | foreach {
    $_.psobject.properties | foreach {
        Write-Host Property Name: $_.name
        Write-Host Values: $_.value
    }
} 

您可以根据需要继续前进。

$json | foreach {
    $_.psobject.properties | foreach {
        $_.value | foreach {
            $_.psobject.properties | foreach {
                write-host Property name: $_.name
                write-host Property value: $_.value
            }
        }
    }
}

Property name: userId
Property value: 1
Property name: firstName
Property value: Krish
Property name: lastName
Property value: Lee
Property name: phoneNumber
Property value: 123456
Property name: emailAddress
Property value: krish.lee@learningcontainer.com
Property name: userId
Property value: 2
Property name: firstName
Property value: racks
Property name: lastName
Property value: jacson
Property name: phoneNumber
Property value: 123456
Property name: emailAddress
Property value: racks.jacson@learningcontainer.com

【讨论】:

  • 是的!这种技术对我来说非常有效......在我递归检查当前 $val 是否为 PSCustomObject 时,需要做一些工作来过滤输出里面的所有东西......有点乱 - 但它有效!谢谢!
【解决方案2】:

通用解决方案补充Doug Maurer's helpful answer

下面的sn-p定义并调用函数Get-LeafProperty,它递归地遍历一个对象图——比如ConvertFrom-Json返回的——并且输出所有叶子 em> 属性值,以及它们在层次结构中的名称路径

# Define a walker function for object graphs:
# Get all leaf properties in a given object's hierarchy,
# namely properties of primitive and quasi-primitive types 
# (.NET primitive types, plus those that serialize to JSON as a single value).
# Output:
#  A flat collection of [pscustomobject] instances with .NamePath and .Value 
#  properties; e.g.:
#   [pscustomobject] @{ NamePath = 'results.users[0].userId'; Value = 1 }
function Get-LeafProperty {
  param([Parameter(ValueFromPipeline)] [object] $InputObject, [string] $NamePath)
  process {   
    if ($null -eq $InputObject -or $InputObject -is [DbNull] -or $InputObject.GetType().IsPrimitive -or $InputObject.GetType() -in [string], [datetime], [datetimeoffset], [decimal], [bigint]) {
      # A null-like value or a primitive / quasi-primitive type -> output.
      # Note: Returning a 2-element ValueTuple would result in better performance, both time- and space-wise:
      #      [ValueTuple]::Create($NamePath, $InputObject)
      [pscustomobject] @{ NamePath = $NamePath; Value = $InputObject }
    }
    elseif ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [System.Collections.IDictionary]) {
      # A collection of sorts (other than a string or dictionary (hash table)), 
      # recurse on its elements.
      $i = 0
      foreach ($o in $InputObject) { Get-LeafProperty $o ($NamePath + '[' + $i++ + ']') }
    }
    else { 
      # A non-quasi-primitive scalar object or a dictionary:
      # enumerate its properties / entries.
      $props = if ($InputObject -is [System.Collections.IDictionary]) { $InputObject.GetEnumerator() } else { $InputObject.psobject.properties }
      $sep = '.' * ($NamePath -ne '')
      foreach ($p in $props) {
        Get-LeafProperty $p.Value ($NamePath + $sep + $p.Name)
      }
    }
  }
}

使用示例:

# Parse sample JSON with multiple hierarchy levels into a [pscustomobject]
# graph using ConvertFrom-Json.
$objectGraphFromJson = @'
{
  "results": {
      "users": [
          {
              "userId": 1,
              "emailAddress": "jane.doe@example.com",
              "attributes": {
                  "height": 165,
                  "weight": 60
              }
          },
          {
              "userId": 2,
              "emailAddress": "john.doe@example.com",
              "attributes": {
                  "height": 180,
                  "weight": 72
              }
          }
      ]
  }
}
'@ | ConvertFrom-Json

# Get all leaf properties.
Get-LeafProperty $objectGraphFromJson

以上产量:

NamePath                                          Value
--------                                          -----
results.users[0].userId                               1
results.users[0].emailAddress      jane.doe@example.com
results.users[0].attributes.height                  165
results.users[0].attributes.weight                   60
results.users[1].userId                               2
results.users[1].emailAddress      john.doe@example.com
results.users[1].attributes.height                  180
results.users[1].attributes.weight                   72

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 2020-07-03
    相关资源
    最近更新 更多