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.

4
  • 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. Commented Jun 6, 2021 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 = @{ … }. Commented Jun 6, 2021 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 Commented Jun 6, 2021 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) Commented Jun 6, 2021 at 17:30

1 Answer 1

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
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.