mnieto
mnieto

Reputation: 3874

select-object -expandproperty with null property

I have a collection of objects with properties like id, username, email, current_sign_in_at, identities. Where Identities property is an array of objects with two properties. This would be a json representation of an object:

{
        "id": 45,
        "name": "Emilio Roche",
        "username": "EROCHE",
        "state": "active",
        "identities": [
            {
                "provider": "ldapmain",
                "extern_uid": "cn=roche\\, emilio,ou=xxxxxxxxxx"
            }    
          ]
    }

But some of the elements in the list do not have the identities property. So, when I do:

Get-Collection | Select-Object id, username  -ExpandProperty identities

I get only those elements with identities property. I need all the entities, with or without identities property

Upvotes: 4

Views: 1805

Answers (2)

mklement0
mklement0

Reputation: 437803

Note: This answer addresses the question as asked, but, judging by what answer was accepted, the real problem must have been different.

Select-Object -ExpandProperty identities id, username outputs an object for each individual identity in the identities array.

In order to include input objects that lack an identities property, you must therefore provide a placeholder dummy identity for them, which is what the following code demonstrates, using placeholder identity [pscustomobject] @{ provider='none'; extern_uid='none' } via an auxiliary Select-Object call that uses a calculated property to ensure the existence of an identities property.

# Sample JSON:
#  * The 1st object has *2* identities,
#  * the 2nd one none.
$json = '[
  {
    "id": 45,
    "name": "Emilio Roche",
    "username": "EROCHE",
    "state": "active",
    "identities": [
      {
          "provider": "ldapmain",
          "extern_uid": "cn=roche\\, emilio,ou=xxxxxxxxxx"
      },    
      {
          "provider": "ad",
          "extern_uid": "cn=roche\\, emilio,ou=yyyyyyyyyy"
      }    
    ]
  },
  {
    "id": 46,
    "name": "A. Non",
    "username": "ANON",
    "state": "dormant"
  }
]'

($json | ConvertFrom-Json) | 
  Select-Object id, username, @{ n='identities'; e={ 
      if ($_.identities) { $_.identities }
      else               { [pscustomobject] @{ provider='none'; extern_uid='none' } } 
    } } |
      Select-Object id, username -ExpandProperty identities 

The above yields:

provider extern_uid                      id username
-------- ----------                      -- --------
ldapmain cn=roche\, emilio,ou=xxxxxxxxxx 45 EROCHE
ad       cn=roche\, emilio,ou=yyyyyyyyyy 45 EROCHE
none     none                            46 ANON

Note how EROCHE is represented twice, once for each identity.

Upvotes: 4

Manuel Batsching
Manuel Batsching

Reputation: 3596

If there are not too many properties to handle, you could use something like this:

Get-Collection | Select-Object id, 
    username,
    @{n='provider';e={$_.identities.provider}}, 
    @{n='extern_uid';e={$_.identities.extern_uid}}

This will return $null on the properties provider and extern_uid for those objects, that do not have the identities property:

id username provider extern_uid                     
-- -------- -------- ----------                     
45 EROCHE   ldapmain cn=roche\, emilio,ou=xxxxxxxxxx
46 EROCHE                                           

EDIT

As mklement0 pointed out, that approach doesn't work, if the identities property holds more than one object.

mklement0's answer has an elegant solution to this problem and should have been the accepted answer.

Upvotes: 6

Related Questions