Loop through Json in powershell - powershell

I have json that I get from an API that returns a value like this
[{
"Location": "/xxx/005D2"
}, {
"Location": "/xxx/020D2"
}, {
"Location": "/xxx/061D2"
}, {
"Location": "/xxx/086D2"
}, {
"Location": "/xxx/100D2"
}]
When I call the URL and access the variable
$installs= Invoke-RestMethod -Uri $installLocation -Method Get;
I get the following
Location
--------------
/xxx/100D2
/xxx/120D2
/xxx/110D2
etc
How can I loop through these so I only access 1 location at a time?

You acutally don't want to loop through JSON, but through a PowerShell object ($installs). You can do that, as with any other PowerShell object.
$installs | ForEach-Object {
$_.Location
}

Related

issues PowerShell POST request with body

I have a bit issue with powershell + invoke-webrequest
This is my body
$pram = #{
"name": "MDE.Windows",
"id": "$resourceId/extensions/MDE.Windows",
"type": "Microsoft.Compute/virtualMachines/extensions",
"location": "westeurope",
"properties": {
"autoUpgradeMinorVersion": true,
"publisher": "Microsoft.Azure.AzureDefenderForServers",
"type": "MDE.Windows",
"typeHandlerVersion": "1.0",
"settings": {
"azureResourceId": "$resourceId",
"defenderForServersWorkspaceId": "$subscriptionId",
"vNextEnabled": "true",
"forceReOnboarding": true,
"provisionedBy": "Manual"
},
"protectedSettings": {
"defenderForEndpointOnboardingScript": "$defenderForEndpointOnboardingScript"
}
}
}
I don't get watch wrong with my body because by looking examples from google this should be right but it still ouputs red
I have tried also with #"{ }"#, #'{ }'#, { }, "{ }" but no matter what I do it is more or less red.
I think your mistaking powershell hash tables for json. Normally you would create a hashtable using powershell syntax, then convert that object into Json. eg
$pram = #{
name= "MDE.Windows";
id= "$resourceId/extensions/MDE.Windows";
} | ConvertTo-Json
You can now pass the json encoded value of $parm to Invoke-WebRequest.
The other option is to create a String and write the JSON yourself:
$paramString = '{"id": "/extensions/MDE.Windows", "name": "MDE.Windows"}'
(but the first solution is probably the solution your looking for).

Building a nested dictionary/hash tables in powershell displays "System.Collections.Hashtable"

I'm trying to create a body for a webrequest which is in the form of a nested dictionary.
$body +=#{}
$body["tables"] = #()
$body["tables"] += #{}
$body["tables"][0]["id"] += #{}
$body["tables"][0]["id"]["columnId"] = "1"
$body["tables"][0]["id"]["fieldType"] = "1"
$body["tables"][0]["textFilter"] = #{"value" = "123"}
$body2Json = ConvertTo-Json $body
When I try to print this, I get the following:
{
"tables": [
{
"id": "System.Collections.Hashtable",
"textFilter": "System.Collections.Hashtable"
}
]
}
Not sure what am I doing wrong here, still new to powershell
You created a pretty complex, multi-node PowerShell object, but the ConvertTo-Json cmdlet only converts the first two levels of depth before it stops.
Fortunately, You can control this behavior with the -Depth parameter like so:
ConvertTo-Json $body -Depth 5
{
"tables": [{
"id": {
"columnId": "1",
"fieldType": "1"
},
"textFilter": {
"value": "123"
}
}]
}

Single value array being converted to String - Powershell

I am converting this to JSON and sending in a POST request but the value of ContextTypes keeps getting converted to string.
$postParams = #{
instance=[PSCustomObject]#{
instanceId= $instanceId;
className="Permission";
schemaName="RBAC";
properties= #{
Name= $Name;
Description= $Description;
ServiceGPRId= 1;
CategoryId= 1;
ContextTypes=#('Object')
};
}
} | ConvertTo-Json
returns:
{
"instance": {
"instanceId": null,
"className": "Permission",
"schemaName": "RBAC",
"properties": {
"CategoryId": 1,
"ServiceGPRId": 1,
"Description": null,
"Name": null,
"ContextTypes": "Object"
}
}}
I have seen other answers and have tried (#(...)) as well, it doesn't work. For some reason, if I define the same name-value pair outside of the properties object, it works fine and returns:
{
"instance": {
"instanceId": null,
"className": "Permission",
"schemaName": "RBAC",
"ContextTypes": [
"Object"
],
"properties": {
"CategoryId": 1,
"ServiceGPRId": 1,
"Description": null,
"Name": null
}
}
}
I also tried converting it to Json using the -InputObject method, but that gives same results.
How do I make sure ContextTypes remains an array?
You need to add -Depth 3 to your ConvertTo-Json call to ensure that your object graph is serialized to its full depth:
#{
instance= [PSCustomObject] #{
instanceId= $instanceId
className="Permission"
schemaName="RBAC"
properties= [PSCustomObject] #{
Name= $Name
Description= $Description
ServiceGPRId = 1
CategoryId = 1
ContextTypes = #('Object')
}
}
} | ConvertTo-Json -Depth 3
Unfortunately, -Depth defaults to 2, which explains your - subtle - symptom: essentially, your array was serialized as its string-expanded value, which yielded just its (only) element (e.g., "$(#('foo'))" yields 'foo').
For background information, see:
this post.
this GitHub issue.

Have PowerShell pass results to Pentaho

I have a PowerShell script that processes a json string. My goal is to have this pass a resultset to Pentaho so I can process it and put it in a database table.
My PowerShell script works as expected outside of Pentaho. I can parse the files and get the information I need without any issues. It's when I try to pass those values is when Pentaho returns goofy results.
Here is my script
$scriptMode = 'GetFileInfo'
$json = '{
"building": [
{
"buildingname": "NAPA Auto Parts",
"files": [{
"sheets": [{
"name": "BATTERY",
"results": [{
"filename": "BATTERY - 1679568711.xlsx",
"sku": "1679568711"
}
]
}
],
"name": "2.15.19.xlsx",
"status": "processed",
"fileId": "c586bba6-4382-42c4-9c29-bffc6f7fe0b6"
}, {
"name": "Oct-Nov 2018 11.30.18.xlsx",
"errors": ["Unknown sheet name: TOILET PLUNGER"],
"status": "failed",
"fileId": "afa7c43f-26dc-421c-b2eb-45ad1e899c42"
}
]
},
{
"buildingname": "O''Reily Auto Parts",
"files": [{
"sheets": [{
"name": "ALTERNATOR",
"results": [{
"filename": "ALTERNATOR - 6.3.19 1629453444.xlsx",
"sku": "1629453444"
}
]
}, {
"name": "OIL FILTER",
"results": [{
"filename": "OIL FILTER - 6.3.19 1629453444.xlsx",
"sku": "1629453444"
}
]
}
],
"name": "6.3.19.xlsx",
"status": "processed",
"fileId": "647089fe-9592-4e2b-984f-831c4acd4d9c"
}
]
}
]
}'
$psdata = ConvertFrom-Json -InputObject $json
IF ($scriptMode -eq "GetFileInfo") {
$psdata.building | foreach-Object {
foreach ($File in $_.files)
{
[PSCustomObject]#{
BuildingName = $_.buildingname
FileName = $File.name
fileId = $File.fileId
Status = $File.status}
}
}
}
ElseIF ($scriptMode -eq "GetErrorInfo") {
$psdata.building | foreach-Object {
foreach ($File in $_.files)
{
[PSCustomObject]#{
BuildingName = $_.buildingname
Errors = $File.errors
SheetName = $File.sheets.name
fileId = $File.fileId} | Where-Object {$_.errors -ne $null}
}
}
}
And here's how I have my transformation setup. I have a table input query that will set the run command for PowerShell based on what I want the script to do (either get file info or get error info).
Then I have the "Execute a process" step run the PowerShell command
This is what is returned in Pentaho vs what PowerShell returns
I'm expecting the results to be returned exactly as PowerShell returns them. I'm hoping I can accomplish this without exporting the data to another format. We have had nothing but issues with the Json Input step in Pentaho, so we chose PowerShell over the "Modified Javascript Value" step in Pentaho.
Any idea how I can get this to return a result set (like a SQL query would return) back to Pentaho?
Most likely your result set is returning the entire thing, just not "tabled" as you expected, it's probably returning the entire table all summed up in one long text format, but still having all the line breaks / column breaks.
Try using Split steps in your pentaho flow to work on the returned String. First off, try using a "Split field to rows" with the delimiter as "${line.separator}".
From there all you to do is pretty much split the whole thing until it is a table in pentaho.

Why is only the first youtube playlist updated, when sending in two youtube playlist updates?

When running the code example below, only the first YouTube playlist ($YouTubePlaylistId1) is updated with an added video ($YouTubeVideoId).
While no update occurs for the second YouTube playlist ($YouTubePlaylistId2).
I don't receive any errors, but could there still be an issue with the json body below? Or is it something else I've missed here?
I've tried to switch around the playlistid, but it's always the first one defined that get's updated.
There's no difference if it's the same playlist id set in both variables: $YouTubePlaylistId1, $YouTubePlaylistId2, with a unique video ($YouTubeVideoId).
Tried multiple variations of the json body ($YouTubePlaylistVideoBody), but that usually ends with an error complaining about the format of the json.
# Set the first yt playlist id
$YouTubePlaylistId1 = "DummyPlaylistId1"
# Set the second yt playlist id
$YouTubePlaylistId2 = "DummyPlaylistId2"
# Set the yt video id
$YouTubeVideoId = "dQw4w9WgXcQ"
# Set access token provided by https://developers.google.com/oauthplayground
$GoogleAccessToken = "DummyAccessToken"
# Set the rest method to yt playlistitems
$YouTubePlaylistVideoUri = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet"
# Set the JSON body
$YouTubePlaylistVideoBody = #"
{
"snippet": {
"playlistId": "$YouTubePlaylistId1",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
}
},
"snippet": {
"playlistId": "$YouTubePlaylistId2",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
}
}
}
"#
# Create new header object
$HeaderValue = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
# Append the Google access token in $GoogleAccessToken
$HeaderValue.Add("Authorization", "Bearer $GoogleAccessToken")
# Invoke rest command
Invoke-RestMethod -Headers $HeaderValue -Uri $Uri -Method "POST" -Body
$YouTubePlaylistVideoBody -ContentType "application/json"
Expected result is that both youtube playlists are updated with an video.
Actual result is that only the first playlist (defined in $YouTubePlaylistVideoBody) is being updated, without any errors reported back.
Edit: Attempted to use two different JSON arrays as below, but they all ends with error "(400) Bad Request":
$YouTubePlaylistVideoBody = #"
{
"snippet": [
"playlistId": "$YouTubePlaylistId1",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
},
"playlistId": "$YouTubePlaylistId2",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
}
]
}
"#
$YouTubePlaylistVideoBody = #"
[
"snippet": {
"playlistId": "$YouTubePlaylistId1",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
}
},
"snippet": {
"playlistId": "$YouTubePlaylistId2",
"resourceId": {
"kind": "youtube#video",
"videoId": "$YouTubeVideoId"
}
}
]
"#