【问题标题】:Return the "Name" of an object that has a specific "Value" in PSObject返回在 PSObject 中具有特定 \"Value\" 的对象的 \"Name\"
【发布时间】:2022-10-30 21:22:17
【问题描述】:

我已使用以下方法将 JSON 文件转换为 PSObject:

$json = Get-Content $filepath -Raw | ConvertFrom-Json

PSObject 现在的一个例子:

Value           : Production
MemberType      : NoteProperty
IsSettable      : True
IsGettable      : True
TypeNameOfValue : System.String
Name            : Environment
IsInstance      : True

我知道您可以通过以下方式获得此价值:

$json.psobject.properties["Environment"].Value

这将返回“生产”

问题

有没有一种方法可以根据值返回名称,例如我如何能够根据名称返回值,如上所示?

IE。我怎样才能得到“环境”返回?

作为背景,我正在编写一个循环遍历所有值的脚本,如果这些值为空,那么我需要打印名称。

【问题讨论】:

  • ($json | Where-Object {$_.Value -eq 'Production'}).Name
  • 谢谢@Theo!只需将 $json 更改为 $json.psobject.properties 就可以了,谢谢!

标签: arrays json powershell properties psobject


【解决方案1】:

Theo 的帮助下,您已经找到了解决方案,但让我把它拼出来,并附上一些背景信息:

# Read a sample object from JSON text.
$fromJson = @'
{
  "Foo": "Bar",
  "Environment": "Production",
  "Other": "Stuff"
}
'@ | ConvertFrom-Json

# Find the name of the property/ies whose value is 'Production'
# -> 'Environment'
$fromJson.psobject.Properties.Where({ $_.Value -eq 'Production' }).Name

笔记:

  • 以上依赖于 PowerShell 在所有对象上公开的intrinsic psobject property,这是一个丰富的反射来源,例如通过.psobject.Properties 对给定对象的属性以及用于过滤的intrinsic .Where() method 进行过滤(性能更好, 功能更丰富的替代 Where-Objectcmdlet)。

  • 代码仅适用于顶层特性从 JSON 解析的对象的数量。如果你需要搜索整个对象图形, IE。嵌套的对于层次结构中任何级别的值的对象,都需要付出更多的努力。

以下示例假定函数 Get-PropertyPathByValue 已经定义(见下文):

# Read a *nested* sample object from JSON text.
$fromJson = @'
{
  "Foo": "Bar",
  "Nested": {
    "More": "Stuff",
    "Environment": "Production"
  },
  "Other": "Stuff"
}
'@ | ConvertFrom-Json

# Find the value 'Production' anywhere in the object hierarchy,
# and return the matching property's name *path* (dot notation).
# -> 'Nested.Environment'
$fromJson | Get-PropertyPathByValue -Value 'Production'

Get-PropertyPathByValue源代码- 注意可以搜索的值类型的限制:

# Finds a *simple* value in the object graphs given and returns the path of 
# matching properties in dot notation (e.g., 'foo.bar`).
# Note: *Simple* means a *single* (non-collection) value that is either:
#  * a string or
#  * an instance of a .NET primitive or similar type (numbers, dates).
function Get-PropertyPathByValue {
  param([Parameter(ValueFromPipeline, Mandatory)] [object] $InputObject, [Parameter(Mandatory)] $Value, [string] $NamePath)
  process {   
    if ($null -eq $InputObject -or $InputObject.GetType().IsPrimitive -or $InputObject.GetType() -in [string], [datetime], [datetimeoffset], [decimal], [bigint]) {
      # A null-like value or a primitive / quasi-primitive type -> output.
      if ($Value -eq $InputObject) { return $NamePath }
    }
    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-PropertyPathByValue $o $Value ($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-PropertyPathByValue $p.Value $Value ($NamePath + $sep + $p.Name)
      }
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-16
    • 2018-04-11
    • 2021-07-10
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多