Powershell command ConvertFrom-Json gives empty objects [duplicate] - json

How to call API inside function. this is my url https://www.gov.uk/bank-holidays.json. I am new for powershell can you help me to do this.
function Holiday {
$list = Invoke-RestMethod -Method Get -Uri https://www.gov.uk/bank-holidays.json
Write-Host "$list"
}
but i am unable to list . can u please help me on that

Invoke-RestMethod automatically parses the API's JSON response into an object [graph] - a nested [pscustomobject] instance or an array thereof (in a manner of speaking, Invoke-RestMethod has ConvertFrom-Json built in).
While very convenient for subsequent OO processing, the resulting objects' display representation isn't very helpful:
Only the top-level properties of the object graph are printed.
Due to a long-standing bug - see GitHub issue #6163 - nested property values may falsely appear to be empty - see this answer for an example.
To quickly visualize the result, you can simply convert back to JSON, using ConvertTo-Json:
function Get-Holiday {
# Call the API, which returns JSON that is parsed into a [pscustomobject]
# graph, and return (output) the result.
Invoke-RestMethod -Method Get -Uri https://www.gov.uk/bank-holidays.json
}
$list = Get-Holiday
# Visualize the object for display by converting it back to JSON.
$list | ConvertTo-Json -Depth 3
Note the unfortunate need to specify -Depth 3 explicitly - see this post for background information.
An alternative visualization can be achieved by piping to Format-Custom:
The resulting for-display representation isn't JSON, but a notation that resembles hashtable literals and is easy to parse visually.
Format-Custom's default depth is 5 (compared to ConvertTo-Json's 2), so you will often get away without a -Depth argument.
Conversely, however, you may need to (temporarily) set the $FormatEnumerationLimit preference variable to ensure that all elements of a collection are visualized; by default, only 4 are, and omitted elements are represented as ….
That said, if you just want to get a quick sense of the structure of the object graph, that may not be a problem.
# Assumes that $list was obtained as above.
$list | Format-Custom
Output (showing just the first object; note the … indicating that the collection contained in the .events property has additional elements that were omitted):
class PSCustomObject
{
england-and-wales =
class PSCustomObject
{
division = england-and-wales
events =
[
class PSCustomObject
{
title = New Year’s Day
date = 2018-01-01
notes =
bunting = True
}
class PSCustomObject
{
title = Good Friday
date = 2018-03-30
notes =
bunting = False
}
class PSCustomObject
{
title = Easter Monday
date = 2018-04-02
notes =
bunting = True
}
class PSCustomObject
{
title = Early May bank holiday
date = 2018-05-07
notes =
bunting = True
}
…
]
}
With respect to processing, here's an example that accesses the first entry for England and Wales:
$list.'england-and-wales'.events[0]
The above yields:
title date notes bunting
----- ---- ----- -------
New Year’s Day 2015-01-01 True

Related

Call API inside powershell function

How to call API inside function. this is my url https://www.gov.uk/bank-holidays.json. I am new for powershell can you help me to do this.
function Holiday {
$list = Invoke-RestMethod -Method Get -Uri https://www.gov.uk/bank-holidays.json
Write-Host "$list"
}
but i am unable to list . can u please help me on that
Invoke-RestMethod automatically parses the API's JSON response into an object [graph] - a nested [pscustomobject] instance or an array thereof (in a manner of speaking, Invoke-RestMethod has ConvertFrom-Json built in).
While very convenient for subsequent OO processing, the resulting objects' display representation isn't very helpful:
Only the top-level properties of the object graph are printed.
Due to a long-standing bug - see GitHub issue #6163 - nested property values may falsely appear to be empty - see this answer for an example.
To quickly visualize the result, you can simply convert back to JSON, using ConvertTo-Json:
function Get-Holiday {
# Call the API, which returns JSON that is parsed into a [pscustomobject]
# graph, and return (output) the result.
Invoke-RestMethod -Method Get -Uri https://www.gov.uk/bank-holidays.json
}
$list = Get-Holiday
# Visualize the object for display by converting it back to JSON.
$list | ConvertTo-Json -Depth 3
Note the unfortunate need to specify -Depth 3 explicitly - see this post for background information.
An alternative visualization can be achieved by piping to Format-Custom:
The resulting for-display representation isn't JSON, but a notation that resembles hashtable literals and is easy to parse visually.
Format-Custom's default depth is 5 (compared to ConvertTo-Json's 2), so you will often get away without a -Depth argument.
Conversely, however, you may need to (temporarily) set the $FormatEnumerationLimit preference variable to ensure that all elements of a collection are visualized; by default, only 4 are, and omitted elements are represented as ….
That said, if you just want to get a quick sense of the structure of the object graph, that may not be a problem.
# Assumes that $list was obtained as above.
$list | Format-Custom
Output (showing just the first object; note the … indicating that the collection contained in the .events property has additional elements that were omitted):
class PSCustomObject
{
england-and-wales =
class PSCustomObject
{
division = england-and-wales
events =
[
class PSCustomObject
{
title = New Year’s Day
date = 2018-01-01
notes =
bunting = True
}
class PSCustomObject
{
title = Good Friday
date = 2018-03-30
notes =
bunting = False
}
class PSCustomObject
{
title = Easter Monday
date = 2018-04-02
notes =
bunting = True
}
class PSCustomObject
{
title = Early May bank holiday
date = 2018-05-07
notes =
bunting = True
}
…
]
}
With respect to processing, here's an example that accesses the first entry for England and Wales:
$list.'england-and-wales'.events[0]
The above yields:
title date notes bunting
----- ---- ----- -------
New Year’s Day 2015-01-01 True

Powershell Json object manipulation

I am hitting a Rest API and collected a gnarly block of Json. I'm running convertfrom-json on that to get a powershell object which I would like to manipulate. Essentially I need to prune a number of field/values.
Its no issue to 'get' the fields I want to remove from the object as I can just drill down to the field and collect the value thats easy, where I am stuck is how to trim off that field from the posh object. Would appreciate any assistance. Thanks.
Example:
$sample_json = #"
{
"fields": {
"field_one": 1,
"field_two": 2,
"field_three": "three",
"field_four": "remove_me",
"field_five": 5
}
}
"#
Clear-Host
$json_object = ConvertFrom-Json -InputObject $sample_json
$json_object
Gives:
fields
------
#{field_one=1; field_two=2; field_three=three; field_four=remove_me; field_five=5}
So the question is how can I remove "field_four" key, and it's value, from $json_object ? Apologies if this is crazy simple; I'm a bit out of touch with Powershell these last few years.
You can remove "field_four" with the Remove method from PSObject.Properties:
$json_object.fields.PSObject.Properties.Remove("field_four")
Use the following statement
$json_object.fields.PSObject.Properties.Remove("field_four")

Format [pscustomobject] instances returned by Invoke-RestMethod or ConvertFrom-Json

I am trying to create a table from a JSON file I am receiving from a RESTful API.
When I print the property of the json object I get an output like this:
PS> Write-Output JSON.Object
Object1 : #{key1=property; key2=property; key3=property; key4=property}
Object2 : #{key1=property; key2=property; key3=property; key4=property}
Object3 : #{key1=property; key2=property; key3=property; key4=property}
Object4 : #{key1=property; key2=property; key3=property; key4=property}
The output I would like to see is this:
Name key1 key2 key3 key4
----- ---- ---- ---- ----
Object1 property property property property
Object2 property property property property
Object3 property property property property
In addition, is it possible to avoid displaying a specific key and it's properties?
Example:
Name key1 key2 key4 # ← Not displaying key3
----- ---- ---- ----
Object1 property property property
Object2 property property property
Object3 property property property
You need to add the parent keyname as a property Name to the nested objects:
$json.Object | ForEach-Object {
foreach ($p in $_.PSObject.Properties) {
$p.Value | Select-Object #{n='Name';e={$p.Name}},*
}
}
Note that PowerShell will render the output in list form by default, since your objects have more than 4 properties. Pipe it through Format-List -AutoSize to get tabular output.
To complement Ansgar Wiecher's elegant answer with background information:
Let's define sample input that simulates a single, nested object converted to a PowerShell [pscustomobject] instance via ConvertFrom-Json:
$objFromJson = [pscustomobject] #{
Object1 = [pscustomobject] #{key1='o11'; key2='o12'; key3='o13'; key4='o14'}
Object2 = [pscustomobject] #{key1='o21'; key2='o22'; key3='o23'; key4='o24'}
Object3 = [pscustomobject] #{key1='o31'; key2='o32'; key3='o33'; key4='o34'}
Object4 = [pscustomobject] #{key1='o41'; key2='o42'; key3='o43'; key4='o44'}
Object5 = [pscustomobject] #{key1='o51'; key2='o52'; key3='o53'; key4='o54'}
}
Outputting $objFromJson gives output that is formatted as in the question.
Why does this result in the output formatting shown in the question?
For types such as [pscustomobject], which do not have explicit formatting definitions defined for them (via *.ps1xml files and loaded implicitly into the session or explicitly via Update-FormatData), PowerShell decides what default formatting to use based on the number of properties of the type:
A type with up to 4 properties implicitly uses Format-Table
a type with 5 or more properties implicitly uses Format-List
The sample input in the question is presumably abridged; with truly only 4 properties, a tabular display would have resulted.
The properties themselves are rendered by calling .PSObject.ToString() on their values, which is typically the same representation you'd get if you referenced the object inside a double-quoted string, except that the latter always uses culture-invariant formatting, whereas .ToString() will respect the current culture, if the type supports it.
In the case of a [pscustomobject] instance, this results in a representation that resembles a hashtable literal, but isn't one (for background information, see this answer); e.g.:
PS> $objFromJson.Object1.PSObject.ToString()
#{key1=o11; key2=o12; key3=o13; key4=o14}
Reshaping the data as desired:
There is no way to use formatting cmdlets such as Format-Table directly to yield the desired output - the data must be reshaped first:
Specifically, the properties of object $objFromJson must be reshaped into a collection of custom objects:
whose Name property contains the name of a given property, and
whose other properties are the properties of the object of that property's value; in other words: the properties of the input property's value must be made properties of the output object itself.
Extracting $objFromJson's properties is facilitated by PowerShell adding (among others) a hidden .PSObject property to all objects, whose own .Properties property contains a collection of all the object's property definitions (name, value, additional metadata such as the type of property, ...); e.g.:
PS> $objFromJson.Object1.PSObject.Properties
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : o11
TypeNameOfValue : System.String
Name : key1
IsInstance : True
# ... remaining properties
Outputting the collection of $objFromJson's property definitions and extracting only the definitions' Name and Value properties is a step in the right direction:
PS> $objFromJson.PSObject.Properties | Select-Object Name, Value
Name Value
---- -----
Object1 #{key1=o11; key2=o12; key3=o13; key4=o14}
Object2 #{key1=o21; key2=o22; key3=o23; key4=o24}
Object3 #{key1=o31; key2=o32; key3=o33; key4=o34}
Object4 #{key1=o41; key2=o42; key3=o43; key4=o44}
Object5 #{key1=o51; key2=o52; key3=o53; key4=o54}
However, we must make the properties of the .Value property direct properties of the output objects to get output with property-individual values.
Ansgar's elegant answer demonstrates how to do that in a single pipeline.
Let me complement it with a reusable helper function derived from it:
function ConvertTo-Collection($InputObject) {
foreach ($obj in $InputObject) {
foreach ($prop in $obj.PSObject.Properties) {
$prop.Value | Select-Object #{ n='Name'; e={ $prop.Name }}, *
}
}
}
With that function in place, the desired output can now be achieved thus:
ConvertTo-Collection $objFromJson | Format-Table
To exclude a specific property, such as key3:
ConvertTo-Collection $objFromJson | Select-Object -ExcludeProperty key3 |
Format-Table

Date type in Powershell ConvertTo-JSON [duplicate]

I want to get the current date as a string in the following format:
\/Date(1411762618805)\/
I have been fighting with PowerShell and have tried the following, but it keeps wrapping the object with unwanted properties. I just need the value
Get-Date | ConvertTo-Json
# returns
{
"value": "\/Date(1411762618805)\/",
"DisplayHint": 2,
"DateTime": "Friday, September 26, 2014 4:16:58 PM"
}
Of course if you try to convert back to an object with ConvertFrom-Json you are back with a .NET Date object.
I have gotten closer with
Get-Date | Select-Object -Property Date | ConvertTo-Json
{
"Date": "\/Date(1411704000000)\/"
}
But it is still wrapped in a Date child property. At the end of the day all I want is a string with Microsoft's ugly JSON format.
I only want to use the built in .NET JSON serializers if possible.
There are two problem properties here, DateTime and DisplayHint and both require a different solution. The DateTime property is a ScriptProperty attached by the extended type system, so it exists on all DateTime objects automatically. You can remove it from all DateTime objects in the current session via Remove-TypeData
Get-TypeData System.DateTime | Remove-TypeData
The DisplayHint property is a NoteProperty that is added by the Get-Date cmdlet. I know of no way to suppress this from serialization. You can remove it explicitly from the DateTime:
Get-Date | foreach { $_.PSObject.Properties.Remove("DisplayHint"); $_ } | ConvertTo-Json
which will output
"\/Date(1411846057456)\/"
This is current date and time, if you only want the date you can do this
Get-Date | select -ExpandProperty Date | ConvertTo-Json
Here we don't have to remove the DisplayHint because it was not attached by Get-Date.
Don't even get me started on the hoops you will have to jump through to convert back to the proper date time object.
So, the wonderful thing about JSON dates is... nothing. They are evil, and deserve to be punished.
So, what is a JSON date? It is the number of milliseconds since Unix Epoc (Jan 1, 1970), well, UTC time that is. So, that's great and all, but how do we get that without using the ConvertTo-JSON cmdlet? Easiest way I know of is this:
[int64]([datetime]::UtcNow)-(get-date "1/1/1970").TotalMilliseconds
That will get you the current date and time formatted for JSON. If you want a specific date or date/time you could do it, but you have to adjust for time zone, which we can do, it just gets long:
$target = "2/2/2014 6:32 PM"
[int64]((get-date $target).addhours((([datetime]::UtcNow)-(get-date)).Hours)-(get-date "1/1/1970")).totalmilliseconds
1391391120000
That would be the kick-off time for the last Super Bowl.
I know this is old but Google led me here. I'm using Invoke-RestMethod to send/receive JSON data, including timestamps in the /Date(1411704000000)/ format. I managed to convert from PowerShell to JSON using the following:
[System.DateTime]$(Get-Date).DateTime
Example:
#{DateTime = [System.DateTime]$(Get-Date).DateTime} | ConvertTo-Json
Returns:
{
"DateTime": "\/Date(1484023637000)\/"
}
Try use [System.Datetime]::Now instead Get-Date cmdlet

How to fetch a JSON file to get a row position from a given value or argument

I'm using wget to fetch several dozen JSON files on a daily basis that go like this:
{
"results": [
{
"id": "ABC789",
"title": "Apple",
},
{
"id": "XYZ123",
"title": "Orange",
}]
}
My goal is to find row's position on each JSON file given a value or set of values (i.e. "In which row XYZ123 is located?"). In previous example ABC789 is in row 1, XYZ123 in row 2 and so on.
As for now I use Google Regine to "quickly" visualize (using the Text Filter option) where the XYZ123 is standing (row 2).
But since it takes a while to do this manually for each file I was wondering if there is a quick and efficient way in one go.
What can I do and how can I fetch and do the request? Thanks in advance! FoF0
In python:
import json
#assume json_string = your loaded data
data = json.loads(json_string)
mapped_vals = []
for ent in data:
mapped_vals.append(ent['id'])
The order of items in the list will be indexed according to the json data, since the list is a sequenced collection.
In PHP:
$data = json_decode($json_string);
$output = array();
foreach($data as $values){
$output[] = $values->id;
}
Again, the ordered nature of PHP arrays ensure that the output will be ordered as-is with regard to indexes.
Either example could be modified to use a mapped dictionary (python) or an associative array (php) if needs demand.
You could adapt these to functions that take the id value as an argument, track how far they are into the array, and when found, break out and return the current index.
Wow. I posted the original question 10 months ago when I knew nothing about Python nor computer programming whatsoever!
Answer
But I learned basic Python last December and came up with a solution for not only get the rank order but to insert the results into a MySQL database:
import urllib.request
import json
# Make connection and get the content
response = urllib.request.urlopen(http://whatever.com/search?=ids=1212,125,54,454)
content = response.read()
# Decode Json search results to type dict
json_search = json.loads(content.decode("utf8"))
# Get 'results' key-value pairs to a list
search_data_all = []
for i in json_search['results']:
search_data_all.append(i)
# Prepare MySQL list with ranking order for each id item
ranks_list_to_mysql = []
for i in range(len(search_data_all)):
d = {}
d['id'] = search_data_all[i]['id']
d['rank'] = i + 1
ranks_list_to_mysql.append(d)