1

I am looking for a way to filter nested objects with PowerShell. Let's say I have a list that contains UPN addresses.

$UPN = "[email protected]", "[email protected]"

In the below object converted to JSON, I want to get only those objects where "Attr1" within whole object contains any address from the above list.

[
    {
        "Id":  "1",
        "Name":  "XYZ",
        "Attr1":  [
                      {
                          "Id":  "1",
                          "UPN":  "[email protected]"
                      },
                      {
                          "Id":  "2",
                          "UPN":  "[email protected]"
                      },
                      {
                          "Id":  "3",
                          "UPN":  "[email protected]"
                      }
                  ],
        "Attr2":  [
                        {
                            "Id":  "1",
                            [...]
                        }
                    ],
        "Attr3":  [
                         {
                             "Id":  "1",
                             [...]
                         },
                         {
                             "Id":  "2",
                             [...]
                        
                         }
                     ]
    },
    {
        "Id":  "2",
        "Name":  "XYZ",
        "Attr1":  [
                      {
                          "Id":  "1",
                          "UPN":  "[email protected]"
                      }
                  ],
        "Attr2":  [
        
                    ],
        "Attr3":  [
                         {
                             "Id":  "1",
                             [...]
                         }
                     ]
    }
]

How to filter such an object? The standard method to not work for me (I am not getting the desired result, losing data):

$CollectionOfObjects | Where-Object {$_.Attr1.UPN -in $UPN} 

How to handle this?

Regards!

1 Answer 1

1

You need to nest Where-Object calls to get the desired result, or, for better performance with in-memory collections, .Where() method calls:

$CollectionOfObjects.Where({ $_.Attr1.Where({ $_.UPN -in $UPN }, 'First') })

Tip of the hat to Manuel Batsching for his help.

Note: The 'First' argument isn't strictly necessary, but can improve performance, as it stops enumerating the elements of the array in .Attr1 as soon as a match is found.

As an aside: Where-Object has no equivalent feature - enumeration invariably continues.
GitHub issue #13834 suggests bringing all the extra features .Where() supports to Where-Object too.


A self-contained example with simplified data:

$UPN = '[email protected]', '[email protected]'

$CollectionOfObjects = ConvertFrom-Json @'
[
  {
      "Id":  "1",
      "Name":  "XYZ1",
      "Attr1":  [
                    {
                        "Id":  "1",
                        "UPN":  "[email protected]"
                    },
                    {
                        "Id":  "2",
                        "UPN":  "[email protected]"
                    },
                    {
                        "Id":  "3",
                        "UPN":  "[email protected]"
                    }
                ],
      "Attr2":  [ ],
      "Attr3":  [ ]
  },
  {
    "Id":  "2",
    "Name":  "XYZ2",
    "Attr1":  [
                  {
                      "Id":  "1",
                      "UPN":  "[email protected]"
                  },
                  {
                      "Id":  "2",
                      "UPN":  "[email protected]"
                  }
              ],
    "Attr2":  [ ],
    "Attr3":  [ ]
  },
  {
      "Id":  "3",
      "Name":  "XYZ3",
      "Attr1":  [
                    {
                        "Id":  "1",
                        "UPN":  "[email protected]"
                    }
                ],
      "Attr2":  [ ],
      "Attr3":  [ ]
  }
]
'@

$CollectionOfObjects.Where({ $_.Attr1.Where({ $_.UPN -in $UPN }, 'First') })

Output, showing that the two objects of interest were successfully identified:

Id    : 1
Name  : XYZ1
Attr1 : {@{Id=1; [email protected]}, @{Id=2; [email protected]}, @{Id=3; [email protected]}}
Attr2 : {}
Attr3 : {}

Id    : 3
Name  : XYZ3
Attr1 : {@{Id=1; [email protected]}}
Attr2 : {}
Attr3 : {}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.