0

We're playing with Inovke-RestMethod response. As a part of response we have an array:

$array = @(
    {
        id = "9916"
        title = "title9916"
    }
    {
        id = "9917"
        title = "title9917"
    }
)

We've noticed that every item in an array is treated as ScriptBlock:

PS C:\> $array | % { $_.GetType() }

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ScriptBlock                              System.Object
True     True     ScriptBlock                              System.Object

How to make every item iterable?

PS. When ScriptBlock is given as:

$scriptblock = {
    id = "9916"
    title = "title9916"
}

we could transform to HashTable with:

PS C:\> $hash = ConvertFrom-StringData -StringData $scriptblock.ToString()

What if ScriptBlock is given as:

$scriptblock = {
    id = "9916"
    title = "title9916"
    details = @{
        name = "name9916"
        count = 128
    }
}

In this case ConvertFrom-StringData won't work.

PS. For those who are curious: we're playing with ManageEngine ServiceDesk Plus v3

https://www.manageengine.com/products/service-desk/sdpod-v3-api/SDPOD-V3-API.html#get-request

Response is given as a PSCustomObject and we only need a certain subset of it. This subset could change in time and it's defined as a list in XML file. Based on that list we should process our response. We think that the best way to achieve this goal is to transform PSCustomObject to XML and use functions:

  • SelectNodes
  • SelectSingleNode
  • GetElementsByTagName

To transform PSCustomObject to XML we're using modified version of the script:

https://www.powershellgallery.com/packages/Traverse/0.5.1085.1/Content/Private%5CConvert-HashTableToXML.ps1

It works perfectly until it comes to an array.

user3719188
  • 590
  • 5
  • 7
  • You can use a `PSCustomObject` instead. To iterate though them, you can use `.GetEnumerator()` method. *Dot notation* will also work when referencing a property: `$Scriptblock.ID`. Just like you mentioned, you can use a hash table. Depends on what fits your needs. – Abraham Zinala Jun 06 '21 at 12:14
  • 1
    ```{ … }``` declares a script block in PowerShell, whereas ```@{ … }``` declares a hashtable. I’m not sure how your Invoke-restMethod is returning an array of script blocks, but try adding a leading ```@``` both to the ```{``` in your ```$array = …``` sample code like you’ve got in the ```details = @{ … }```. – mclayton Jun 06 '21 at 12:58
  • 2
    Please show us how you captured/manufactured the `$array`. This seems very weird format if it is returned from `Invoke-RestMethod` – Theo Jun 06 '21 at 13:19
  • I don't think I've ever seen this behavior from `Invoke-RestMethod`, very curious to know what kind of API you're querying. You can evaluate your scriptblocks as hashtables with `Invoke-Expression` by prepending a `@`: `$array |Invoke-Expression -Command {'@'+$_.Ast.ToString()}` (**this is dangerous and you should *never* use this in production**) – Mathias R. Jessen Jun 06 '21 at 17:30

1 Answers1

1

As mentioned in the comments, your $array is not valid JSON - I can imagine the returned type "scriptblock" can be misleading, but in this case it's about a block of powershell script, not javascript.

I'm not sure what happened to its contents, but this is how it would look if it were JSON:

$array = @"
    [{
        id: "9916",
        title: "title9916"
    },
    {
        id: "9917",
        title: "title9917"
    }]
"@

And this is how to get usable data from it:

# Produces PSCustomObjects, which is probably what you're looking for:
$result = ConvertFrom-Json $array
Leon Bouquiet
  • 4,159
  • 3
  • 25
  • 36