Search code examples
jsonpowershellrest

Parsing JSON from API using PowerShell - issue with hash table addition (i dont know where the hash table comes from)


I am trying to parse some information through an API to view the status of running jobs in a vendor system. I am not a dev and don't really use API or JSON much, so this is literally draft code to see if I could understand or teach myself what was needed, I only have access to PowerShell and I have to admit to being puzzled.

First I get the list of running jobs and that works fine:

$headers = @{}
$headers.Add("accept", "application/json")
$headers.Add("X-ApiKeys", "<key details in here>")
$response = Invoke-WebRequest -Uri <URL inserted here> -Method GET -Headers $headers

if ($response.StatusCode -eq 200) {
    $LongList = ConvertFrom-Json $response.content
    $ShortList = $LongList.Jobs
}

then I try to iterate though that list and get the status of each job making a summary of the results in a new PS Object for further processing.

   $response4=@{}
   foreach{$job in $shortlist){
   $response2 = Invoke-WebRequest -Uri <URL here> -Method GET -Headers $headers
   $response3 = ConvertFrom-Json $response2.content
   $response4 += New-Object PSObject -Property @{
        status = $response3.status
        progress = $response3.progress
        id = $job.id
        name = $job.name
  }

This will run if I don't use += for the new object, but obviously that overwrites each jobs details, whenever I use the += it gives the error:

A hash table can only be added to another hash table.

The properties of $response3 that I am pushing into $response4 are not hash tables they are note properties

$response3 | gm

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
progress    NoteProperty long progress=100
status      NoteProperty string status=completed 

The fields I am using from $jobs are also note property:

Name                   MemberType   Definition
----                   ----------   ----------
Equals                 Method       bool Equals(System.Object obj)
GetHashCode            Method       int GetHashCode()
GetType                Method       type GetType()
ToString               Method       string ToString()
control                NoteProperty bool control=True
creation_date          NoteProperty long creation_date=1709024561
enabled                NoteProperty bool enabled=True
has_triggers           NoteProperty bool has_triggers=False
id                     NoteProperty long id=172
last_modification_date NoteProperty long last_modification_date=1709029693
legacy                 NoteProperty bool legacy=False
name                   NoteProperty string name=Isero - 

Can someone please give me some pointers, I am a bit lost. I hoped to end up with a new object that contained some information from the list of jobs and the status of each job.


Solution

  • What you wanted was most likely to define an array $response4 = @() instead of a hashtable $response4 = @{}, however there is a much easier way to go about it. You should also use Invoke-RestMethod to query your API instead of Invoke-WebRequest. The Json response will be automatically converted into objects with it.

    if ($response.StatusCode -eq 200) {
        $LongList = ConvertFrom-Json $response.content
        $result = foreach ($job in $LongList.Jobs) {
            $res = Invoke-RestMethod -Uri <uri> -Method GET -Headers $headers
    
            [pscustomobject]@{
                status   = $res.status
                progress = $res.progress
                id       = $job.id
                name     = $job.name
            }
        }
    
        # after that loop all summary is in `$result`
    }