How does Invoke-RestMethod parse a JSON response into a PS object

234 views Asked by At

I am querying the Microsoft Graph API using Powershell and Invoke-RestMethod. My query is:

$GraphAPIReturn = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accesstoken)"} -Uri $GraphAPIResource -Method Post -Body $body -ContentType "application/json"

When the result is returned, I can display the GraphAPIReturn variable, and get some data that looks like:

TotalRowCount : 920
Schema        : {@{Column=AppInstallState; PropertyType=String}, @{Column=AppInstallState_loc; PropertyType=String}, @{Column=AppInstallStateDetails; PropertyType=String}, @{Column=AppInstallStateDetails_loc; PropertyType=String}…}
Values        : {S1 Installed E0  39c23e0b-0098-4eb4-9613-232a005eee82 6.96.170 False  5010bc04-d22f-46ba-94bb-4bd3213ad13f Machine-Name   1 0 10/10/2023 10:13:30 Windows 10.0.19045.3570 82633388-108c-4ea9-842e-ff9a849f5159 Username Email, S1 Installed E0  
            39c23e0b-0098-4eb4-9613-232a005eee82 6.96.170 False  f8ec0b7a-044a-4098-be27-b680072a3b83 Machine-Name   1 0 12/10/2023 10:38:23 Windows 10.0.22621.2428 b7c24328-af42-408a-9f3b-dd23b7108fb4 Username Email, S1 Installed E0  
            39c23e0b-0098-4eb4-9613-232a005eee82 6.96.170 False  1204947b-45e4-44db-8276-c4cfa73c676d Machine-Name   1 0 28/09/2023 09:07:43 Windows 10.0.22621.2428 ada75844-368f-445e-9e8c-21c57c8bae6e Username Email, S1 Installed E0  
            39c23e0b-0098-4eb4-9613-232a005eee82 6.96.170 False  2747782c-fdd7-4b76-b983-8e5694021a60 Machine-Name   1 0 16/09/2023 21:57:46 Windows 10.0.22621.2428 d61099b3-f4d3-4e19-bcb8-1481d098b848 username Email…}
SessionId     : 
AppName       : 'Our Intune App Name'

If I call $GraphAPIReturn.Values, I am expecting to get the Values property of the returned object, with the data being just what was shown for the Values property in the example above.

Instead, I get one of these for each returned entry:

Length         : 19
LongLength     : 19
Rank           : 1
SyncRoot       : {S1, Installed, E0, …}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 19
AppName        : 'Our Intune App Name'

This looks odd to me, as does not seem to match what is shown in the original variable. If I try to get to the SyncRoot property, it gives me the same data as just showing Values.

What's odd, is if I do exactly the same thing I am doing in the Intune portal, and pull the JSON response from Edge developer tools, I can put this into ConvertFrom-JSON and it then behaves as expected. I can call the Values property, and it gives me the data in a format I would expect.

My question is, does Invoke-RestMethod parse the JSON differently to ConvertFrom-JSON? If so, how do I need to change my approach to working with the returned object? If not, what have I gotten wrong in my commands that causes it to parse differently?

EDIT: Example of the JSON returned from Intune portal in Edge developer tools below (truncated results to keep it small):

{"TotalRowCount":917,"Schema":[{"Column":"AppInstallState","PropertyType":"String"},{"Column":"AppInstallState_loc","PropertyType":"String"},{"Column":"AppInstallStateDetails","PropertyType":"String"},{"Column":"AppInstallStateDetails_loc","PropertyType":"String"},{"Column":"ApplicationId","PropertyType":"String"},{"Column":"AppVersion","PropertyType":"String"},{"Column":"AssignmentFilterIdsExist","PropertyType":"SByte"},{"Column":"AssignmentFilterIdsList","PropertyType":"String"},{"Column":"DeviceId","PropertyType":"String"},{"Column":"DeviceName","PropertyType":"String"},{"Column":"ErrorCode","PropertyType":"Int32"},{"Column":"HexErrorCode","PropertyType":"String"},{"Column":"InstallState","PropertyType":"Int32"},{"Column":"InstallStateDetail","PropertyType":"Int32"},{"Column":"LastModifiedDateTime","PropertyType":"DateTime"},{"Column":"Platform","PropertyType":"String"},{"Column":"UserId","PropertyType":"String"},{"Column":"UserName","PropertyType":"String"},{"Column":"UserPrincipalName","PropertyType":"String"}],"Values":[["S1","Installed","E0","","39c23e0b-0098-4eb4-9613-232a005eee82","6.96.170",false,"","5010bc04-d22f-46ba-94bb-4bd3213ad13f","CPC-james-NSYIT","","",1,0,"2023-10-10T10:13:30","Windows 10.0.19045.3570","82633388-108c-4ea9-842e-ff9a849f5159","Allison, James","[email protected]"],["S1","Installed","E0","","39c23e0b-0098-4eb4-9613-232a005eee82","6.96.170",false,"","f8ec0b7a-044a-4098-be27-b680072a3b83","FD-2do7AN5hEMv2","","",1,0,"2023-10-12T10:38:23","Windows 10.0.22621.2428","b7c24328-af42-408a-9f3b-dd23b7108fb4","Gowen, Michael","[email protected]"]],"SessionId":""}

EDIT 2: Adding screenshots to show output displayed.

Invoke-RestMethod full output: Invoke-RestMethod main response output

Invoke-RestMethod Values property output: Invoke-RestMethod Values property

ConvertFrom-JSON full output: ConvertFrom-JSON full output

ConvertFrom-JSON Values property output: ConvertFrom-JSON Values property output

EDIT 3: URL being queried:

 https://graph.microsoft.com/beta/deviceManagement/reports/getDeviceInstallStatusReport

Request body:

$body = @{
    select = @(
        "DeviceName"
        "UserPrincipalName"
        "Platform"
        "AppVersion"
        "InstallState"
        "InstallStateDetail"
        "AssignmentFilterIdsExist"
        "LastModifiedDateTime"
        "DeviceId"
        "ErrorCode"
        "UserName"
        "UserId"
        "ApplicationId"
        "AssignmentFilterIdsList"
        "AppInstallState"
        "AppInstallStateDetails"
        "HexErrorCode"
    )
    skip = 0
    top = 50
    filter = "(ApplicationId eq '$ApplicationID')"
    orderBy = @(
    )
}
$body = $body | ConvertTo-Json

PSVersionTable:

Name                           Value
----                           -----
PSVersion                      7.3.9
PSEdition                      Core
GitCommitId                    7.3.9
OS                             Microsoft Windows 10.0.19044
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
1

There are 1 answers

0
Eds On

Thanks to everyone who assisted me in the comments on my questions.

I believe my issue with parsing of data and recalling variables, was due to the fact I was modifying someone else's script, that had several nested functions returning the results from Invoke-WebRequest.

I was tweaking the inner most function and having issues, but when working on the outer most function, I was able to successfully recall the values in a way/format I would expect to do normally, and that matched the manual ConvertFrom-JSON commands