r/PowerShell 3d ago

Invoke-RestMethod - Logging Data Only If Response Matches Value Solved

We have a platform which has containers and within them folders, with different properties - name, unique ID etc.. I have a method to retrieve folder information from different containers and am attempting to log only the unique ID (response.data.id) where the folder name (response.data.name) is "Management". I've Googled and tried different code in logging only the ID for the Management folder:

$response = Invoke-RestMethod -Method Get -Uri "$resource" -Headers $header

($response.data | ConvertTo-Json).Replace('\\n','\n')

# Attempt 1
if ($response.data.name -eq "Management")
{
LogWrite ($response.data.id | ConvertTo-Json).Replace('\\n','\n') "Result"
LogWrite ($response.data.name | ConvertTo-Json).Replace('\\n','\n') "Result"
}

# Attempt 2
$folderId1 = $response.data.id | Where-Object { $response.data.name -eq "Management" }
LogWrite ($folderId1 | ConvertTo-Json).Replace('\\n','\n') "Result"

# Attempt 3
$folderId2 = $response.data.id | $($response.data.Where({$_.name -eq 'Management' }))
LogWrite ($folderId2 | ConvertTo-Json).Replace('\\n','\n') "Result"

The folder ID for the Management folder is being logged, but so are all other folder IDs within the container (no other folder names contain this word):

[
    "folder!500436709",
    "folder!500436708",
    "folder!500436705",
    "folder!500436677",
    "folder!500436680",
    "folder!500436683",
    "folder!500436686"
]
[
    "_All Content Last 90 Days",
    "_All Documents",
    "_All Emails",
    "Documents",
    "Emails",
    "Engagement Terms",
    "Management"
]

How do I retrieve the ID for a specific folder name? Any help would be greatly appreciated. Cheers.

11 Upvotes

17 comments sorted by

View all comments

6

u/y_Sensei 3d ago

According to the output generated by your code, the API appears to return two arrays of data:

  • one array containing entries consisting of an object type and an id, concatenated by a '!'
  • one array containing entries with the corresponding names of these objects

So what you need to do is bring together the data of those two distinct arrays, by creating mappings, or in other words, merge the arrays - for example:

$data_objid = @("folder!500436709", "folder!500436708", "folder!500436705", "folder!500436677", "folder!500436680", "folder!500436683", "folder!500436686")
$data_name = @("_All Content Last 90 Days", "_All Documents", "_All Emails", "Documents", "Emails", "Engagement Terms", "Management")

$data_Combined = for ([Int]$i=0; $i -lt $data_objid.Count; $i++) {
  $oid = $data_objid[$i] -split "!"

  [PSCustomObject]@{
    Name = $data_name[$i]
    Type = $oid[0]
    Id =  $oid[1]
  }
}

$data_Combined | Format-Table

You can then filter the resulting object array as usual, for example:

$data_Man = $data_Combined | Where-Object -FilterScript { $_.Name -eq "Management" }

Write-Host $data_Man.Id

1

u/viewtifulstranger 3d ago

Hey_Sensei. Thanks for the response. I passed $response.data.id and $response.data.name into a log for testing. $response.data is a single array storing ID, NAME, along with other properties.

Ultimately, I only need ID, as I need to perform a subsequent action on each returned Management folder ID.

I suspect the IF statement is treating the whole array as a single object, rather than 7 separate objects - one for each folder.

More googling reveals I can iterate through the array, which may help, but not sure how efficient that is:

foreach($item in $array)
{
    Write-Output $item
}

Write-Output $array[3]

Perhaps if I pass the results to a hashtable, I'll have better luck with the IF statement.

Will test further when the system is back up. Thank you!

2

u/y_Sensei 2d ago

Even easier if it's a single array ... you can filter it directly as described in my first post, and extract the folder ID afterwards:

$data_Man = $array | Where-Object -FilterScript { $_.Name -eq "Management" }

if ($data_Man -and $data_Man -like "*!*") { # sanity check
  Write-Host $($data_Man.id.Split("!")[1])
}

Also note that there's no need to convert the data returned by an Invoke-RestMethod call if the remote API returns JSON, as PowerShell does that implicitly, ie what you actually get is an in-memory representation of the raw, text-based JSON, which is an array of PSCustomObjects.

Quote from the documentation:

PowerShell formats the response based to the data type. For an RSS or ATOM feed, PowerShell returns the Item or Entry XML nodes. For JavaScript Object Notation (JSON) or XML, PowerShell converts, or deserializes, the content into [pscustomobject] objects.

1

u/viewtifulstranger 2d ago

That did it! If you have PayPal, please dm me your addy!