Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with Powershell invoke-restmethod and json response

VERY newbie here with Powershell and JSON so may need a little extra help. Not a coder, fyi.

I'm working with Dell's API to retrieve warranty information on machines. I'd like to do it in Powershell if possible.

Here's my code so far -

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("apikey", 'mykey')
$response = Invoke-RestMethod https://sandbox.api.dell.com/support/assetinfo/v4/getassetwarranty/servicecode -Headers $headers -contenttype 'application/json'

If I look at $response, here is the output -

AssetWarrantyResponse : {@{AssetHeaderData=; ProductHeaderData=; AssetEntitlementData=System.Object[]}}
InvalidFormatAssets   : @{BadAssets=System.Object[]}
InvalidBILAssets      : @{BadAssets=System.Object[]}
ExcessTags            : @{BadAssets=System.Object[]}
AdditionalInformation :

Did some digging and found if I use the below code, I can start seeing actual data -

$response.AssetWarrantyResponse|fl

AssetHeaderData      : @{BUID=11; ServiceTag=....
ProductHeaderData    : @{SystemDescription=Op....
AssetEntitlementData : {@{StartDate=2017-11-2....

I see there is a command for convertfrom-json. Looks like this will take the response and make it a little easier to work with in Powershell. But I can't for the life of me make this work. I'm trying to pull out a few pieces of data from the AssetHeaderData and AssetEntitlementData above. I'm sure I could do some regex's, but if there's an easier way, I'm all for it!

Any help is appreciated. Thanks!

like image 962
Pat Avatar asked Jul 31 '18 15:07

Pat


People also ask

What is invoke-RestMethod in PowerShell?

Description. The Invoke-RestMethod cmdlet sends HTTP and HTTPS requests to Representational State Transfer (REST) web services that return richly structured data. PowerShell formats the response based to the data type. For an RSS or ATOM feed, PowerShell returns the Item or Entry XML nodes.

Can we call REST API from PowerShell?

To call a REST API from the Windows PowerShell, you should use the Invoke-RestMethod cmdlet. A call to an API is simply a request through HTTP or HTTPS. So, you will need a URL to which the API will be sent. You can find detailed information about the URL to call to get data from API documentation.


1 Answers

You're doing great! What you're seeing is PowerShell's system of displaying data on the screen. Since PowerShell tends to deal in complex objects, it's not just formatted string output you are dealing with like you might see from regular shell commands.

In this case, Invoke-RestMethod has automatically done the equivalent of ConvertFrom-Json for you, that is, it has taken the JSON returned from the API and created an object out of it.

The object has various properties, like .AssetWarrantyResponse, each of which could be a value or an array or another object.

So what you're seeing in the output, in your first dump of $response in your question, is the properties the response object has, and the values of those properties.

The values look funny because they are themselves objects, some of which contain arrays, and they are difficult to format all at once.

You've already figured out that you can reference the properties directly, for example by using $response.AssetWarrantyResponse.

When you look at that, you see more properties, which are also objects. I don't think it's going to be nested much more deeply based on the output you posted.

So to look at what's inside the properties you want, just keep digging away:

$response.AssetWarrantyResponse.AssetHeaderData
$response.AssetWarrantyResponse.AssetEntitlementData

You don't need regex for this at all, because the data is already broken up appropriately.

If there's something else you want to do with it, edit it into your question (or post a new one if warranted) and we can help with that too.

Update based on comment

Tab completion can be finicky. But as I look at your data again, I think I see why you saw what you saw, and tab completion was working correctly.

AssetWarrantyResponse is a single property, it will tab complete. Its value is an array. So trying to do .AssetWarrantyResponse.AssetHeaderData will not tab complete, because it's not a property of the object (an array).

If you did $response.AssetWarrantyResponse[0].AssetHeaderData then tab completion would work.

The reason it "works" when just typing it, is because of a change in PowerShell v3.

Before v3, if you have an array of objects and wanted to get an array of the .Thing property of each object, you would have to enumerate it yourself:

$things = foreach($item in $arr) {
    $arr.Thing
}

v3 added a neat feature where you could just do $things = $arr.Thing and it handles it all for you. But since each item in the array might be completely different and have different properties, tab completion doesn't try to go into every one of them and read them and decide what to tab complete; you'd have to dereference yourself a single item and then tab completion will work as expected.

So even if you want to use the v3 goodness, you can use tab completion with a little extra typing:

$response.AssetWTAB[0].AssetHTAB

Then just go back and delete [0].

Just remember that if that property is an array, you should probably expect that .AssetWarrantyResponse.AssetHeaderData could also be an array, and so you must deal with that case appropriately in whatever comes next.

If you don't care about that situation and just want the first item, use [0] (or use [-1] if you only want the last one). Point is, if you want to assume it will only ever be a single element, make sure the code handles that assumption so it doesn't do strange things on an edge case.

like image 108
briantist Avatar answered Sep 29 '22 08:09

briantist