Azure functions & Powershell: get response in plain JSON - json

Trying out some new features in Azure; Azure Functions running Powershell. One thing I'm struggling with for a while: I cannot get the output in plain JSON, instead in seems formatted and includes escape characters and is messed up double quoting.
function.json:
{
"bindings": [
{
"name": "req",
"type": "httpTrigger",
"direction": "in",
"webHookType": "genericJson",
"methods": [
"post",
"head",
"trace"
]
},
{
"name": "res",
"type": "http",
"direction": "out"
}
],
"disabled": false
}
run.ps1:
$ApiURI="http://avwx.rest/api/metar.php?station=ymml&format=JSON"
$Result = Invoke-RestMethod -Uri $ApiURI
Out-File -Encoding Ascii -FilePath $res -inputObject $Result
Results in following response:
"\r\n\r\nAltimeter : 1015\r\nCloud-List : {FEW 035}\r\nDewpoint : 11\r\nFlight-Rules : VFR\r\nOther-List : {}\r\nRaw-Report : YMML 210900Z 17010KT 9999 FEW035 19/11 Q1015 NOSIG\r\nRemarks : NOSIG\r\nRemarks-Info : \r\nRunway-Vis-List : {}\r\nStation : YMML\r\nTemperature : 19\r\nTime : 210900Z\r\nUnits : #{Altimeter=hPa; Altitude=ft; Temperature=C; Visibility=m; \r\n Wind-Speed=kt}\r\nVisibility : 9999\r\nWind-Direction : 170\r\nWind-Gust : \r\nWind-Speed : 10\r\nWind-Variable-Dir : {}\r\n\r\n\r\n\r\n"
But what I expect is something like:
{
"Altimeter": "1016",
"Cloud-List": [],
"Dewpoint": "12",
"Flight-Rules": "VFR",
"Other-List": [],
"Raw-Report": "YMML 210930Z 17011KT CAVOK 18/12 Q1016 NOSIG",
"Remarks": "NOSIG",
"Remarks-Info": {},
"Runway-Vis-List": [],
"Station": "YMML",
"Temperature": "18",
"Time": "210930Z",
"Units": {
"Altimeter": "hPa",
"Altitude": "ft",
"Temperature": "C",
"Visibility": "m",
"Wind-Speed": "kt"
},
"Visibility": "9999",
"Wind-Direction": "170",
"Wind-Gust": "",
"Wind-Speed": "11",
"Wind-Variable-Dir": []
}
What could be wrong here?

I'm not sure how you got that result, since Invoke-RestMethod store the data in the ResponseData property.
When you use Invoke-RestMethod it will convert the json data to a Powershell Object. In your run.ps1 it looks like you are going to save the PS Object to a file, not the JSON data.
If you are not going to modify the JSON data, it's really no use to convert it to a PSObject. So you could use Invoke-webrequest instead.
But in case you want to modify it.
$uri = "http://avwx.rest/api/metar.php?station=ymml&format=JSON"
$request = Invoke-RestMethod -Uri $uri
#Get the result and convert it back to JSON
$Result = $request.responseData | ConvertTo-Json
$Result | Out-File .\data.json -Encoding Ascii

#David - Yes, the following works for me in Azure Functions.
a. run.ps1 file content
$ApiURI="http://avwx.rest/api/metar.php?station=ymml&format=JSON"
$Result = Invoke-RestMethod -Uri $ApiURI | ConvertTo-Json
Out-File -Encoding Ascii -FilePath $res -inputObject $Result
b. Request result both in Azure Functions Portal and Postman.
{
"Altimeter": "1016",
"Cloud-List": [
[
"FEW",
"016"
]
],
"Dewpoint": "13",
"Flight-Rules": "VFR",
"Other-List": [],
"Raw-Report": "YMML 212100Z 28005KT 9999 FEW016 15/13 Q1016 NOSIG",
"Remarks": "NOSIG",
"Remarks-Info": {},
"Runway-Vis-List": [],
"Station": "YMML",
"Temperature": "15",
"Time": "212100Z",
"Units": {
"Altimeter": "hPa",
"Altitude": "ft",
"Temperature": "C",
"Visibility": "m",
"Wind-Speed": "kt"
},
"Visibility": "9999",
"Wind-Direction": "280",
"Wind-Gust": "",
"Wind-Speed": "05",
"Wind-Variable-Dir": []
}

Related

Converting JSON to NDJSON with Powershell

I'm trying to convert a text file that has an array of json objects to an NDJSON formatted file for another team to consume.
I've almost got it, except for one problem. I have an array of objects nested inside the JSON (which then has nested arrays and objects inside of it, the structure gets pretty complex, I'll include a sample below) and for whatever reason, when I use ConvertFrom-JSON it drops this nested array and in my output, I end up with a blank string for that key, instead of the nested array object. I tried using the -Depth flag but when I do that my output file ends up blank, which doesn't make a ton of sense to me. I don't have a whole lot of experience with powershell, so I'm not really sure where I'm going wrong here.
Code:
$JSONSourceFile = Get-Content -Path "input/sample.json" | ConvertFrom-JSON
$NDJSONTargetFile = "output/sample.json"
New-Item $NDJSONTargetFile -ItemType file
for ( $i = 0 ; $i -lt $JSONSourceFile.Length ; $i++) {
$item = $JSONSourceFile.item($i)
$row = ($item | ConvertTo-JSON -Compress)
Add-Content $NDJSONTargetFile $row
}
Input File:
[
{
"id": "1",
"TransactionDttm": "2021-02-22T15:45:00:00.000-05:00",
"Array1": [
{
"UserID": "ak2354",
"Preferences": [
{
"CagegoryID": "01",
"CategoryName": "Reminder",
"Channels": [
{
"ChannelID": "1",
"ChannelName": "Email",
"Preference": "Y"
},
{
"ChannelID": "2",
"ChannelName": "Text",
"Preference": "N"
}
]
}
]
}
]
},
{
"id": "2",
"TransactionDttm": "2021-02-22T15:45:00:00.000-05:00",
"Array1": [
{
"UserID": "ak1234",
"Preferences": [
{
"CagegoryID": "01",
"CategoryName": "Reminder",
"Channels": [
{
"ChannelID": "1",
"ChannelName": "Email",
"Preference": "Y"
},
{
"ChannelID": "2",
"ChannelName": "Text",
"Preference": "Y"
}
]
}
]
}
]
},
{
"id": "3",
"TransactionDttm": "2021-02-22T15:45:00:00.000-05:00",
"Array1": [
{
"UserID": "ak5678",
"Preferences": [
{
"CagegoryID": "01",
"CategoryName": "Reminder",
"Channels": [
{
"ChannelID": "1",
"ChannelName": "Email",
"Preference": "N"
},
{
"ChannelID": "2",
"ChannelName": "Text",
"Preference": "N"
}
]
}
]
}
]
}
]
And then when I convert it to the output, this is what I get:
{"id":"1","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak2354","Preferences":""}]}
{"id":"2","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak1234","Preferences":""}]}
{"id":"3","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak5678","Preferences":""}]}
Thanks to the comment from Doug Maurer I figured it out, I was adding -Depth to my ConvertFrom-Json command when it should have been in my ConvertTo-Json command. This is the final script and what it gives me:
$JSONSourceFile = Get-Content -Path "input/sample.json" | ConvertFrom-JSON
$NDJSONTargetFile = "output/sample.json"
New-Item $NDJSONTargetFile -ItemType file
for ( $i = 0 ; $i -lt $JSONSourceFile.Length ; $i++) {
$item = $JSONSourceFile.item($i)
$row = ($item | ConvertTo-JSON -Compress -Depth 20)
Add-Content $NDJSONTargetFile $row
}
and the output:
{"id":"1","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak2354","Preferences":[{"CagegoryID":"01","CategoryName":"Reminder","Channels":[{"ChannelID":"1","ChannelName":"Email","Preference":"Y"},{"ChannelID":"2","ChannelName":"Text","Preference":"N"}]}]}]}
{"id":"2","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak1234","Preferences":[{"CagegoryID":"01","CategoryName":"Reminder","Channels":[{"ChannelID":"1","ChannelName":"Email","Preference":"Y"},{"ChannelID":"2","ChannelName":"Text","Preference":"Y"}]}]}]}
{"id":"3","TransactionDttm":"2021-02-22T15:45:00:00.000-05:00","Array1":[{"UserID":"ak5678","Preferences":[{"CagegoryID":"01","CategoryName":"Reminder","Channels":[{"ChannelID":"1","ChannelName":"Email","Preference":"N"},{"ChannelID":"2","ChannelName":"Text","Preference":"N"}]}]}]}

JSON file specific keywork via powershell

I want to get lines which are serviceArea equal Skype like below.
{
"id": 127,
"serviceArea": "Skype",
"serviceAreaDisplayName": "Skype for Business Online and Microsoft Teams",
"urls": [
"*.skype.com"
],
"tcpPorts": "80,443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 128,
"serviceArea": "Common",
"serviceAreaDisplayName": "Microsoft 365 Common and Office Online",
"urls": [
"*.config.office.net",
"*.manage.microsoft.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 130,
"serviceArea": "Common",
"serviceAreaDisplayName": "Microsoft 365 Common and Office Online",
"urls": [
"lpcres.delve.office.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
},
{
"id": 146,
"serviceArea": "Skype",
"serviceAreaDisplayName": "Skype for Business Online and Microsoft Teams",
"urls": [
"statics.teams.microsoft.com"
],
"tcpPorts": "443",
"expressRoute": false,
"category": "Default",
"required": true
}
My desired output :
*.skype.com
statics.teams.microsoft.com
Assuming your JSON is wrapped in an array (as mentioned in comments above), you could do something like this to filter the data.
param(
$jsonFile = "$PSScriptRoot\data.json",
$likeFilter = "*Skype*"
)
$convertedObjects = Get-Content -Path $jsonFile | ConvertFrom-Json
$result = $convertedObjects | Where-Object { $_.serviceArea -like $likeFilter }
$result
Your JSON is invalid due to is has no root element. As I see, it is array (list)
$text = #'
[
<your text here>
]
'#
After that, you can select urls
$result = $text |
ConvertFrom-Json |
Where-Object { $_.serviceArea -eq 'Skype' } |
ForEach-Object { return $_.urls }

How to Add a new JsonArray Property to a Existing Json Property using PowerShell

I already have a Json value got from calling an API, I want to add a new Json List to the exiting Property, So
#calling some API in a loop Start
$apijson = Invoke-WebRequest -Uri $api -ErrorAction SilentlyContinue | ConvertFrom-Json
$response = $apijson| ConvertTo-Json
$null = $data.Add($response);
#calling some API in a loop End
My apiJson will look like the below
{
"host": "tet",
"port": 443,
"protocol": "http",
"isPublic": false,
"status": "READY",
"startTime": 1585220081665,
"testTime": 1585220127003,
"engineVersion": "2.1.0",
"criteriaVersion": "2009q",
"endpoints": [
{
"delegation": 1
}
]
}
Now I have a custom new JsonArray
[
{
"name": "TLE",
"Strength": 128
},
{
"name": "TLS",
"trength": 415
}
]
I want to add the above JsonArray to my original Json Property which makes a full Json like below
{
"host": "tet",
"port": 443,
"protocol": "http",
"isPublic": false,
"status": "READY",
"startTime": 1585220081665,
"testTime": 1585220127003,
"engineVersion": "2.1.0",
"criteriaVersion": "2009q",
"endpoints": [
{
"delegation": 1
}
]
},
"Strength": [
{
"name": "TLE",
"Strength": 128
},
{
"name": "TLS",
"trength": 415
}
]
I tried with Addmember, Concatination nothing working unfortunately.
This is for when you are adding Strength as a property to an existing single object (converted from JSON). When using Add-Member, you need to force your new object to be a single array object.
$apijson = Invoke-WebRequest -Uri $api -ErrorAction SilentlyContinue | ConvertFrom-Json
$newjson = #'
[
{
"name": "TLE",
"Strength": 128
},
{
"name": "TLS",
"trength": 415
}
]
'# | ConvertFrom-Json
$apijson | Add-Member -Type NoteProperty -Name 'Strength' -Value #($newjson)
$apijson | ConvertTo-Json -Depth 10

Get the node value from json in powershell

I have json body in powershell variable and want to get value from it.
Json Body :
"value": [
{
"id": 1,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Default",
"isHosted": false,
"poolType": "automation",
"size": 3
},
{
"id": 2,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Hosted",
"isHosted": true,
"poolType": "automation",
"size": 10
},
{
"id": 4,
"scope": "3e93f9e6-f427-48e1-b37b-994d196e1121",
"name": "Hosted VS2017",
"isHosted": true,
"poolType": "automation",
"size": 10
}]
I want to get the id value where name=Hosted VS2017 i.e 4
powershell :
Write-Host "json body:" $projects
$id = $projects.value | where { $_.name -eq "Hosted VS2017" }
Write-Host "id :" $id
You need to convert your JSON into a powershell object before you can work with it:
$projects = $projects | ConvertFrom-Json
Then you can access its members:
#requires -Version 3
$projects.value | ? name -eq 'Hosted VS2017'

Bitbucket API Invoke-RestMethod, Powershell, Get data to Json file,webscraping

I try to do exact same thing that Bibucket API explained
BitBucket says/explain
https://confluence.atlassian.com/bitbucket/repository-resource-423626331.html
GET https://api.bitbucket.org/2.0/repositories/{owner}/{repo_slug}
{
"scm": "hg",
"has_wiki": true,
"description": "Site for tutorial101 files",
"links": {
"watchers": {
"href": "https://api.bitbucket.org/2.0/repositories/tutorials/tutorials.bitbucket.org/watchers"
},
"commits": {
"href": "https://api.bitbucket.org/2.0/repositories/tutorials/tutorials.bitbucket.org/commits"
},
"self": {
"href": "https://api.bitbucket.org/2.0/repositories/tutorials/tutorials.bitbucket.org"
},
"html": {
"href": "https://bitbucket.org/tutorials/tutorials.bitbucket.org"
},
"avatar": {
"href": "https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2012/Nov/28/tutorials.bitbucket.org-logo-1456883302-9_avatar.png"
},
"forks": {
"href": "https://api.bitbucket.org/2.0/repositories/tutorials/tutorials.bitbucket.org/forks"
},
"clone": [{
"href": "https://bitbucket.org/tutorials/tutorials.bitbucket.org",
"name": "https"
}, {
"href": "ssh://hg#bitbucket.org/tutorials/tutorials.bitbucket.org",
"name": "ssh"
}],
"pullrequests": {
"href": "https://api.bitbucket.org/2.0/repositories/tutorials/tutorials.bitbucket.org/pullrequests"
}
},
"fork_policy": "allow_forks",
"name": "tutorials.bitbucket.org",
"language": "html/css",
"created_on": "2011-12-20T16:35:06.480042+00:00",
"full_name": "tutorials/tutorials.bitbucket.org",
"has_issues": true,
"owner": {
"username": "tutorials",
"display_name": "tutorials account",
"uuid": "{c788b2da-b7a2-404c-9e26-d3f077557007}",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/users/tutorials"
},
"html": {
"href": "https://bitbucket.org/tutorials"
},
"avatar": {
"href": "https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2013/Nov/25/tutorials-avatar-1563784409-6_avatar.png"
}
}
},
"updated_on": "2014-11-03T02:24:08.409995+00:00",
"size": 76182262,
"is_private": false,
"uuid": "{9970a9b6-2d86-413f-8555-da8e1ac0e542}"
}
I would like to do exact same thing by using powershell.
So, I made a code.
$username = ""
$password = ""
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$response=Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Uri https://bitbucket.org/susco/azuretoquickbase -Method Get
$response
I am sure that I could log in bitbucket since I saw the content of " $responce".
then, like Bitbucket says, I added the code like this to echo out Json file .
$username = ""
$password = ""
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$response=Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Uri https://bitbucket.org/susco/azuretoquickbase -Method Get
$response
$json = $response.Content|ConvertFrom-Json
$json.data.summaries
but it is causing error
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At line:11 char:27
+ $json = $response.Content|ConvertFrom-Json
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
The point is I am sure that I could log in and get to the page bitbucket says, but it is not getting json file and null error.
I want exactly to echo out like Bitbuckets page, How can i do that?
Invoke-RestMethod automatically converts JSON results into objects. If you want just the raw result, use Invoke-WebRequest and get the content property.
Or in your case, since it seems you want the object, just use $json = Invoke-RestMethod ....