With Theo's help you've already found the solution, but let me spell it out, with some background information:
# 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
Note:
The above relies on the intrinsic psobject
property that PowerShell exposes on all objects, which is a rich source of reflection, such as on a given object's properties via .psobject.Properties
, as well as on the intrinsic .Where()
method for filtering (a better-performing, feature-richer alternative to the Where-Object
cmdlet).
The code only works for top-level properties of the object(s) parsed from JSON. If you need to search an entire object graph, i.e. nested objects for values at any level of the hierarchy, more effort is needed.
The following example assumes that function Get-PropertyPathByValue
has already been defined (see below):
# 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
source code - note the limitation on what types of values can be searched for:
# 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)] [AllowNull()] [object] $InputObject, [Parameter(Mandatory)] [AllowNull()] $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)
}
}
}
}