Como você pode testar se um objeto tem uma propriedade específica?

91

Como você pode testar se um objeto tem uma propriedade específica?

Agradeço o que posso fazer ...

$members = Get-Member -InputObject $myobject 

e depois foreachatravés do $members, mas há uma função para testar se o objeto tem uma propriedade específica?

Informações adicionais: o problema é que estou importando dois tipos diferentes de arquivo CSV, um com duas colunas e outro com três. Não consegui fazer o cheque funcionar com "Property", apenas com "NoteProperty" ... seja qual for a diferença

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
fonte
6
($object.property -ne $null)?
arco444
2
Faz diferença se a propriedade existe, mas tem um $nullvalor
Mateus
@ arco444 não - isso requer que a propriedade exista para ter sucesso. - Se você tiver dados dinâmicos (ou seja, de uma solicitação da web) em que algumas linhas nem mesmo especificam essa propriedade, a verificação falhará. :(
BrainSlugs83

Respostas:

98

Como isso?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
fonte
16
Esta resposta funciona apenas para powerShell v3 ou superior. O seguinte deve funcionar mesmo com o powerShell v2 e superior: [bool] ($ file.psobject.Properties | where {$ _. Name -eq "myPropertyNameToTest"})
AstralisSomnium
32
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"é melhor. Não há necessidade de se preocupar com a possível correspondência de padrões, e você também não precisará converter para Booleano.
Bacon Bits de
2
E se o objeto tiver a propriedade ThisisMyPropertye você quiser verificar MyProperty? Todas as soluções nesta resposta resultarão em um falso positivo.
Zoltán Tamási
3
@KolobCanyon Isso não funcionará no Modo estrito.
user2864740
1
Este código dará um falso positivo se, por exemplo, você estiver testando "Count" e o objeto tiver uma propriedade chamada "ThingCount".
dan-gph
68

Você pode usar Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paulo
fonte
12
Melhor resposta IMHO. Isso funciona com objetos .NET que não têm um membro PSobject. Também podemos remover a opção -Membertype se não nos importarmos com qual tipo de membro o objeto contém - apenas o nome do membro. Muito útil com objetos Invoke-RestMethod ou ConvertFrom-Json!
Mister_Tom
2
Sintaxe curta sem verificar o tipo if($var | Get-Member Property){ }if($var | gm Property){ }
:,
Esta é na minha opinião a melhor resposta.
Kiran Hegde
25

Isso é sucinto e legível:

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

Podemos colocá-lo em uma função:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
fonte
Adoro essa resposta, mas parece não funcionar em alguns casos em que a resposta de CB funciona.
edwin
Ou, onde "succinct" = "lixo desnecessário introduzido via Modo estrito sem um bom caso de uso de fallback" (ou seja, sem ?.equivalente): | Isso também falhará para certas variações de $MyObject, notavelmente $ null. Esse não era o caso com o encadeamento nulo fora do Modo estrito.
user2864740
5

Eu tenho usado o seguinte que retorna o valor da propriedade, como seria acessado via$thing.$prop , se a "propriedade" existir e não lançar uma exceção aleatória. Se a propriedade "não existe" (ou tem um valor nulo), então $nullé retornado: esta abordagem funciona em / é útil para o modo estrito , porque, bem, vou pegar todos.

Acho essa abordagem útil porque permite que Objetos personalizados PS, objetos .NET normais, HashTables PS e coleções .NET como o Dicionário sejam tratados como "equivalente digitado em pato" , que considero um ajuste bastante adequado para PowerShell.

Claro, isso não atende à definição estrita de "tem uma propriedade" .. à qual esta questão pode ser explicitamente limitada. Se aceitar a definição mais ampla de "propriedade" assumida aqui, o método pode ser modificado trivialmente para retornar um booleano.

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

Exemplos:

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"

E, este comportamento pode não ser [sempre] desejado .. ie. não é possível distinguir entre x.Counte x["Count"].

user2864740
fonte
2

Se você estiver usando StrictMode e o psobject estiver vazio, ocorrerá um erro.

Para todos os efeitos, isso fará:

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

Para mim MyProperty" -in $MyObject.PSobject.Properties.Namenão funcionou, no entanto

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

trabalho

sebke CCU
fonte
1

Realmente semelhante a uma verificação de javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
fonte
1
Isso pode não funcionar se a propriedade realmente tiver o valor $ null.
Tola Odejayi
8
Isso falhará se o PowerShell estiver no modo estrito.
Ian Kemp
@IanKemp O que é o modo estrito? Gosta da Política de Execução?
Kolob Canyon,
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - essencialmente, é o equivalente em PS ao JavaScript use strict.
Ian Kemp,
1
Isso também não funcionará se a propriedade existir e estiver definida como $ false.
1

Só para esclarecer dado o seguinte objeto

$Object

Com as seguintes propriedades

type        : message
user        : john.doe@company.com
text        : 
ts          : 11/21/2016 8:59:30 PM

O seguinte é verdadeiro

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

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

Portanto, as respostas anteriores que verificam explicitamente a propriedade pelo nome são a maneira mais correta de verificar se essa propriedade não está presente.

John mello
fonte
1

Basta verificar em relação a null.

($myObject.MyProperty -ne $null)

Se você não definiu PowerShell como StrictMode , isso funcionará mesmo se a propriedade não existir:

$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
fonte
2
Pelo que posso ver, isso funciona se a propriedade existe e é $ null, mas não se a propriedade não existe - tentar acessá-la para fazer a verificação de nulo lança uma exceção.
Peter
@Peter Você pode fornecer um exemplo de verificação de nulo lançando uma exceção quando a propriedade não existe? Eu adicionei um exemplo em que uma propriedade não existe e não há exceção.
Shaun Luttin
2
Execute isto: 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}e você obterá um erro A propriedade 'StartDate' não pode ser encontrada neste objeto. No entanto , preciso qualificar meu comentário - você não entenderá se Strictmode não estiver definido. Eu sempre tenho definido, então nunca percebi até que eu testei para isso! Ainda assim, acho que a maioria das pessoas usa (ou deveria usar) 'Set-Strictmode'.
Peter
2
Provavelmente melhor se você qualificar sua resposta, e eu removerei meu voto negativo? Todo mundo aprendeu algo, que é o ponto :-)
Peter
0

Acabei com a seguinte função ...

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
fonte
0

Recentemente, mudei para definir o modo estrito - versão 2.0 e meus testes nulos falharam.

Eu adicionei uma função:

#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
}

Agora eu codifico

if (exists $run main) { ...

ao invés de

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

e estamos a caminho. Parece funcionar em objetos e hashtables

Como um benefício indesejado, é menos digitação.

Steve Pritchard
fonte
Para nulo ou vazio, sempre usei: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}
-1

Acabei de começar a usar o PowerShell com PowerShell Core 6.0 (beta) e o seguinte simplesmente funciona:

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

ou

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
fonte
1
Not with strictmode on
Casper Leon Nielsen
-1

Você pode verificar com:

($Member.PropertyNames -contains "Name") isso irá verificar a propriedade nomeada

Tom Stryhn
fonte
-1

Para identificar quais objetos em uma matriz têm uma propriedade

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
corky
fonte
Falha em StrictMode quando a propriedade não existe.
user2864740