¿Cómo se puede probar si un objeto tiene una propiedad específica?

93

¿Cómo se puede probar si un objeto tiene una propiedad específica?

Aprecio que puedo hacer ...

$members = Get-Member -InputObject $myobject 

y luego a foreachtravés del $members, pero ¿hay una función para probar si el objeto tiene una propiedad específica?

Información adicional: El problema es que estoy importando dos tipos diferentes de archivos CSV, uno con dos columnas y el otro con tres. No pude hacer que el cheque funcionara con "Propiedad", solo con "NoteProperty" ... cualquiera que sea la diferencia

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
fuente
6
($object.property -ne $null)?
arco444
2
¿Importa si la propiedad existe pero tiene un $nullvalor?
Matt
1
@ arco444 nope - eso requiere que la propiedad exista para que tenga éxito. - Si tiene datos dinámicos (es decir, de una solicitud web) donde algunas filas ni siquiera especifican esa propiedad, esa verificación fallará. :(
BrainSlugs83

Respuestas:

103

¿Me gusta esto?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
fuente
16
Esta respuesta solo funciona para powerShell v3 o superior. Lo siguiente debería funcionar incluso con powerShell v2 y superior: [bool] ($ file.psobject.Properties | donde {$ _. Name -eq "myPropertyNameToTest"})
Patrick
33
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"es mejor. No hay necesidad de preocuparse por la posible coincidencia de patrones, y tampoco necesitará convertir a booleano.
Bocados de tocino
2
¿Qué pasa si el objeto tiene la propiedad ThisisMyPropertyy le gustaría verificar MyProperty? Todas las soluciones en esta respuesta resultarán en un falso positivo.
Zoltán Tamási
3
@KolobCanyon Eso no funcionará en el modo estricto.
user2864740
1
Este código dará un falso positivo si, por ejemplo, estabas probando "Count" y el objeto tenía una propiedad llamada "ThingCount".
dan-gph
72

Puedes usar Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paul
fuente
12
Mejor respuesta en mi humilde opinión. Esto funciona con objetos .NET que no tienen un miembro PSobject. También podemos eliminar la opción -Membertype si no nos importa qué tipo de miembro contiene el objeto, solo el nombre del miembro. ¡Muy útil con los objetos Invoke-RestMethod o ConvertFrom-Json!
Mister_Tom
2
Sintaxis corta sin comprobar el tipo:, if($var | Get-Member Property){ }incluso más corto pero menos legible:if($var | gm Property){ }
zett42
En mi opinión, esta es la mejor respuesta.
Kiran Hegde
25

Esto es conciso y legible:

"MyProperty" -in $MyObject.PSobject.Properties.Name

Podemos ponerlo en una función:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
fuente
Me encanta esta respuesta, pero parece que no funciona en algunos casos en los que la respuesta de CB sí.
edwin
O, donde "sucinto" = "basura innecesaria introducida a través del modo estricto sin un buen caso de uso alternativo" (es decir, sin ?.equivalente): | Esto también fallará para ciertas variaciones de $MyObject, notablemente $ null. Este no fue el caso con el encadenamiento nulo fuera del Modo Estricto.
user2864740
5

He estado usando lo siguiente que devuelve el valor de la propiedad, ya que se accedería a través de$thing.$prop , si la "propiedad" existiera y no arrojara una excepción aleatoria. Si la propiedad "no existe" (o tiene un valor nulo), $nullse devuelve: este enfoque funciona en / es útil para el modo estricto , porque, bueno, Gonna Catch 'em All.

Encuentro este enfoque útil porque permite que los objetos personalizados de PS, los objetos .NET normales, las tablas hash de PS y las colecciones de .NET como Dictionary se traten como "equivalentes de tipo pato" , lo que considero que encaja bastante bien con PowerShell.

Por supuesto, esto no cumple con la definición estricta de "tiene una propiedad" ... a la que esta pregunta puede limitarse explícitamente. Si acepta la definición más amplia de "propiedad" asumida aquí, el método puede modificarse trivialmente para devolver un valor booleano.

Function Get-PropOrNull {
    param($thing, [string]$prop)
    Try {
        $thing.$prop
    } Catch {
    }
}

Ejemplos:

Get-PropOrNull (Get-Date) "Date"                   # => Monday, February 05, 2018 12:00:00 AM
Get-PropOrNull (Get-Date) "flub"                   # => $null
Get-PropOrNull (@{x="HashTable"}) "x"              # => "HashTable"
Get-PropOrNull ([PSCustomObject]@{x="Custom"}) "x" # => "Custom"
$oldDict = New-Object "System.Collections.HashTable"
$oldDict["x"] = "OldDict"
Get-PropOrNull $d "x"                              # => "OldDict"

Y, este comportamiento podría no ser [siempre] deseable ... es decir. no es posible distinguir entre x.County x["Count"].

usuario2864740
fuente
3

MyProperty" -in $MyObject.PSobject.Properties.NameSin embargo, para mí no funcionó

$MyObject.PSobject.Properties.Name.Contains("MyProperty")

trabajos

sebke CCU
fuente
2

Si está utilizando StrictMode y el psobject puede estar vacío, le dará un error.

A todos los efectos, esto servirá:

    if (($json.PSobject.Properties | Foreach {$_.Name}) -contains $variable)
Ádám Kovács
fuente
1

Real similar a una verificación de javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
fuente
1
Es posible que esto no funcione si la propiedad realmente tiene el valor $ null.
Tola Odejayi
8
Esto fallará si PowerShell está en modo estricto.
Ian Kemp
@IanKemp ¿Qué es el modo estricto? ¿Te gusta la política de ejecución?
Kolob Canyon
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - esencialmente es el equivalente de PS a JavaScript use strict.
Ian Kemp
1
Esto tampoco funcionará si la propiedad existe y se establece en $ false.
1

Solo para aclarar dado el siguiente objeto

$Object

Con las siguientes propiedades

type        : message
user        : [email protected]
text        : 
ts          : 11/21/2016 8:59:30 PM

Lo siguiente es cierto

$Object.text -eq $NULL
$Object.NotPresent -eq $NULL

-not $Object.text
-not $Object.NotPresent

Entonces, las respuestas anteriores que verifican explícitamente la propiedad por nombre son la forma más correcta de verificar que esa propiedad no esté presente.

John Mello
fuente
1

Simplemente verifique con nulo.

($myObject.MyProperty -ne $null)

Si no ha configurado PowerShell en StrictMode , esto funciona incluso si la propiedad no existe:

$obj = New-Object PSObject;                                                   
Add-Member -InputObject $obj -MemberType NoteProperty -Name Foo -Value "Bar";
$obj.Foo; # Bar                                                                  
($obj.MyProperty -ne $null);  # False, no exception
Shaun Luttin
fuente
2
Por lo que puedo ver, esto funciona si la propiedad existe y es $ null, pero no si la propiedad no existe; intentar acceder a ella para hacer la verificación nula arroja una excepción.
Peter
@Peter ¿Puede proporcionar un ejemplo de la verificación nula que lanza una excepción cuando la propiedad no existe? He agregado un ejemplo en el que una propiedad no existe y no hay excepción.
Shaun Luttin
2
Ejecute esto: Set-Strictmode -version Latest;$obj = ConvertFrom-Json -InputObject '{"name":"test", "version":"1.1.0"}';If($obj.StartDate -ne $null){Write-Verbose -Message $obj.startDate -Verbose}y obtendrá un error La propiedad 'StartDate' no se puede encontrar en este objeto. Sin embargo , necesito calificar mi comentario; no lo recibe si no se establece Strictmode. Siempre lo tengo configurado, ¡así que nunca me di cuenta hasta que probé esto! Aún así, creo que la mayoría de la gente usa (o debería usar) 'Set-Strictmode'.
Peter
2
Probablemente sea mejor si calificas tu respuesta y eliminaré mi voto negativo. Todos han aprendido algo, que es el punto :-)
Peter
0

Terminé con la siguiente función ...

function HasNoteProperty(
    [object]$testObject,
    [string]$propertyName
)
{
    $members = Get-Member -InputObject $testObject 
    if ($members -ne $null -and $members.count -gt 0) 
    { 
        foreach($member in $members) 
        { 
            if ( ($member.MemberType -eq "NoteProperty" )  -and `
                 ($member.Name       -eq $propertyName) ) 
            { 
                return $true 
            } 
        } 
        return $false 
    } 
    else 
    { 
        return $false; 
    }
}
SteveC
fuente
0

Recientemente cambié para establecer la versión 2.0 en modo estricto y mis pruebas nulas fallaron.

Agregué una función:

#use in strict mode to validate property exists before using
function exists {
  param($obj,$prop)
  try {
    if ($null -ne $obj[$prop]) {return $true}
    return $false
  } catch {
    return $false
  }
  return $false
}

Ahora codifico

if (exists $run main) { ...

más bien que

if ($run.main -ne $null) { ...

y estamos en camino. Parece funcionar en objetos y tablas hash

Como beneficio no deseado, es menos mecanografiado.

Steve Pritchard
fuente
Para nulo o vacío, siempre he usado: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}
0

Solo quería agregar algo a la discusión, porque pasé horas depurando un código que funcionaba en otro lugar.

Respuesta de CB. funciona bien para hacer coincidir la variable con los nombres de las propiedades (como cadenas). El problema comenzó cuando la variable coincidía con una parte del nombre de una propiedad.

if([bool]($allFiles.PSobject.Properties.name -match $_.Name) -ne $true){

Más tarde lo usé para referirme a la propiedad de un objeto, pero como solo coincidía con una parte de otra propiedad, por lo que no existía una propiedad real con ese nombre exacto, la operación devolvió el valor 'nulo'.

Solo más tarde utilicé la solución propuesta por dan-gph , que es muy ordenada:

if([bool]($_.Name -in $allFiles.PSobject.Properties.Name) -ne $true){

Esto aseguró que los dos valores fueran idénticos . Sabía dónde buscar, pero aún así fue doloroso incluso darme cuenta de que el problema es que varios nombres coinciden con cadenas de 2 caracteres. prefijo pero por lo demás igual.

Byron
fuente
-1

Acabo de comenzar a usar PowerShell con PowerShell Core 6.0 (beta) y lo siguiente simplemente funciona:

if ($members.NoteProperty) {
   # NoteProperty exist
}

o

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
fuente
1
No con modo estricto activado
Casper Leon Nielsen
-1

Puede consultar con:

($Member.PropertyNames -contains "Name") esto comprobará la propiedad nombrada

Tom Stryhn
fuente
-1

Para identificar cuál de los objetos de una matriz tiene una propiedad

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
taponado
fuente
Falla en StrictMode cuando la propiedad no existe.
user2864740