Search code examples
powershellapipowerbi-datasource

ConvertFrom-JSON to variables for POST further on to PowerBI


I am fetching API data from a URL which is formatted as below:

{
  "printers" : [ {
    "name" : "printsrv01\\printer01",
    "status" : "OK",
    "lastPrintJobSeconds" : 6495,
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.51"
  }, {
    "name" : "printsrv01\\printer02",
    "status" : "OK",
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.52"
  }, {
    "name" : "printsrv02\\printer03",
    "status" : "OK",
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.53"
  }, {
    "name" : "printsrv01\\printer04",
    "status" : "OK",
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.54"
  }, {
    "name" : "printsrv02\\printer05",
    "status" : "OK",
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.55"
  }, {
    "name" : "printsrv01\\printer06",
    "status" : "OK",
    "lastPrintJobSeconds" : 183162,
    "heldJobsCount" : 0,
    "physicalPrinterId" : "net://192.168.0.56"
  } ],
  "heldJobCountTotal" : 0,
  "heldJobsCountMax" : 0
}

I have managed to convert the data from JSON using following code:

while ($true) {
    $request = "http://serveradress:80/api/health/printers?Authorization=GHSKAskas0a5as5FFDA22asD"
    Invoke-WebRequest  $request |
        ConvertFrom-Json |
        select -Expand printers |
}

I am using PowerBI where I would like to upload the data. This can be done using the below code if my values are stored in variables.

$payload = @{
    "name" = $name
    "status" = $status
    "lastPrintJobSeconds" = $lastPrintJobSeconds
    "heldJobsCount" = $heldJobsCount
    "physicalPrinterId" = $physicalPrinterId
}
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))

How can I put each printer information in each variable to send it to the PowerBI datasource used for display?


Edit:

I tried to use the solution suggested by @TheldesOfMark:

$endpoint = "https://api.powerbi.com/beta/aaa555v22-66888-ccc6-95aa-0dfb5dc31330/datasets/aaa555a666-6547-4250-950c-25s5sd5s5s5s5/rows?key=65asd55asd45asd45asd5as5d4!%54dsa5f45fc4zd56fc4"

while ($true) {
    $request = "http://server:80/api/health/printers?Authorization=asd54asas5dSSd55sd4as65d4ASDA"
    Invoke-WebRequest  $request |
        ConvertFrom-Json |
        select -Expand printers |

    foreach ($printer in $printers) {
        $payload = @{
            "name" = $printer.name
            "status" = $printer.status
            "lastPrintJobSeconds" = $printer.lastPrintJobSeconds
            "heldJobsCount" = $printer.heldJobsCount
            "physicalPrinterId" = $printer.physicalPrinterId
        }
        Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))
        Write-Host "Name: " $printer.name " Status: " $printer.status " lastPrintJobSeconds: " $printer.lastPrintJobSeconds " heldJobsCount: " $printer.heldJobsCount " physicalPrinterId: " $printer.physicalPrinterId
    }
    sleep 2
}
}

but it generates the following errors:

At line:10 char:22
+     foreach ($printer in $printers) {
+                       ~~
Unexpected token 'in' in expression or statement.
At line:10 char:21
+     foreach ($printer in $printers) {
+                      ~
Missing closing ')' in expression.
At line:4 char:1
+ {
+ ~
Missing closing '}' in statement block or type definition.
At line:10 char:34
+     foreach ($printer in $printers) {
+                                   ~
Unexpected token ')' in expression or statement.
At line:22 char:5
+     }
+     ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

It seems like the foreach loop is the issue? If I don't convert from JSON it doesn´t give any errors but I doesn't get any data out if I try without converting first.

Edit 2

Changed the Invoke-WebRequest to below and Write Output works it print the data correct. But I get error on the Invoke-RestMethod:

$printers = Invoke-WebRequest 'http://server:80/api/health/printers?Authorization=asd54asas5dSSd55sd4as65d4ASDA' | ConvertFrom-Json | select -Expand printers

The errorcode is as followed:

Invoke-RestMethod : {"error":{"message":"The request was blocked by KeyBlocker "}}
At line:14 char:9
+         Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @( ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Edit 3

$endpoint = "PowerBI_URL"
Invoke-WebRequest 'API_URL' |
    ConvertFrom-Json |
    Select-Object -Expand printers |
    ForEach-Object {
        Invoke-RestMethod -Method Post -Uri "$endpoint" (ConvertTo-Json @($_))
    }

Error code:

Invoke-RestMethod : A positional parameter cannot be found that accepts argument '[
    {
        "name":  "printsrv01\\printer01",
        "status":  "OK",
        "heldJobsCount":  0,
        "physicalPrinterId":  "net://192.168.0.51"
    }
]'.
At line:6 char:9
+         Invoke-RestMethod -Method Post -Uri "$endpoint" (ConvertTo-Json @($_))
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-RestMethod], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Not all values seems to be printed. Missing some.

Edit 4 - Working script

$endpoint = "https://api.powerbi.com/beta/nnf5d2dsf1-4588-88gh-b6a4-0dfb5dc31330/datasets/55562ee92-9c7d-8850-854g-1a39asdd8a4b/rows?key=ljrethjkreRDFG545REWFGGDF0DFGDGF"

while ($true) {
    $printers = Invoke-WebRequest 'http://server/api/health/printers?Authorization=sdfkjdsf044s21sDSFsdf54sdf' | ConvertFrom-Json | select -Expand printers

    foreach ($printer in $printers) {
        $payload = @{
            "name" = $printer.name
            "status" = $printer.status
            "lastPrintJobSeconds" = $printer.lastPrintJobSeconds
            "heldJobsCount" = $printer.heldJobsCount
            "physicalPrinterId" = $printer.physicalPrinterId
        }
        Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))
        #Write-Host "Name: " $printer.name " Status: " $printer.status " lastPrintJobSeconds: " $printer.lastPrintJobSeconds " heldJobsCount: " $printer.heldJobsCount " physicalPrinterId: " $printer.physicalPrinterId
        sleep 1
    }

}

Solution

  • Ansgar's answer is the best answer, in my opinion. But in case there's some reason you need to have this information available to other PS processes. You can cast the variables from your current script by just looping through the array you built and assigning the variables.

    ForEach($printer in $printers){
        $payload = @{
            "name" = $printer.name
            "status" = $printer.status
            "lastPrintJobSeconds" = $printer.lastPrintJobSeconds
            "heldJobsCount" = $printer.heldJobsCount
            "physicalPrinterId" = $printer.physicalPrinterId
        }
        Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))
    }