Adding array objects to a JSON with a property name in powershell - json

I've to retrieve products and it's details and save it together in a json file. Unfortunately the name and details cannot be retrieved from the same API, I gotta use 2 different API. So I run a code inside a for loop to retrieve the list of product names as well as its details as follows:
For($i=0; $i -lt $cart.total; $i++)
{
$query = 'dummy value with the cart number'
$productName = Invoke-RestMethod -Uri 'https://abc' -Body $query -Method Post
$details = Invoke-RestMethod -Uri 'https://xyz' -Body $query -Method Post
}
All this works, and below is sample data in $productname and $details.
$productName
"iPhone"
$details
"data":[
{"Moduleid": "1", "propertyName": "camera", "value": "12MP"},
{"Moduleid" : "43", "propertyName":"battery", "value": "4000MAj"}
]
However what I am trying to do is to save the $productName and $details into a json as follows:
{
"iPhone 7":[
{"Moduleid": "1", "propertyName": "camera", "value": "12MP"},
{"Moduleid" : "423", "propertyName":"battery", "value": "3000MAh"}
],
"S10+": [
{"Moduleid": "21", "propertyName": "camera", "value": "12MP"},
{"Moduleid" : "43", "propertyName":"battery", "value": "4000MAh"}
]
}
I've tried several ways but couldn't reach any conclusion. Please let me know how can these to variable datas be put into a json format as shown above.
Thank you

The question doesn't make clear what each query is returning. Generally speaking, you need to convert the return JSON from both queries into objects then merge the objects into the objects you really want. The run those objects through ConvertTo-Json which should do the trick. The source object structure is what results in the JSON text etc...
It would look something like below, but again, I have to guess at the starting point, for example I'm sure that $productName isn't a flat array, but is itself JSON.
# For test
$productName = "iPhone","S10+"
# For test
$details =
#"
{
"Data": [{
"Moduleid": "1",
"propertyName": "camera",
"value": "12MP"
},
{
"Moduleid" : "43",
"propertyName": "battery",
"value": "4000MAj"
}]
}
"# |
ConvertFrom-Json
$Results =
For( $i = 0; $i -lt $productName.count; ++$i )
{
[PSCustomObject]#{
$productName[$i] = $details.data[$i]
}
}
$Results | ConvertTo-Json
This would give back:
[
{
"iPhone": {
"Moduleid": "1",
"propertyName": "camera",
"value": "12MP"
}
},
{
"S10+": {
"Moduleid": "43",
"propertyName": "battery",
"value": "4000MAj"
}
}
]
Not quite what you're looking for, but should at least demonstrate the point.
Note: Normally I would look for a common property between the 2
returns to relate the data. Absent that I used the array index. Again
part of the reason this doesn't look right.
If you can please edit the question to include the return JSON from both queries, then we can refine the above.

I created a hashtable like:
$hashTable = [HashTable]::New(0, [StringComparer]::Ordinal)
This is so that the keys are case sensitive. Normally if you create it as #{}, it won't be case sensitive.
Then i mapped the key and value to the hash table as follows,
$hashTable.Add($productName.data.name,$details.data)
Now, I convert it to Json as I wanted it using ConvertTo-Json
$hashTable| ConvertTo-Json | Out-File $outputPath

Related

Extract Value from JSON Using PowerShell based on condition

I have the captured the JSON response in variable $releaseDefinitions. With this i want to extract the "ID" as "4598" when i pass the "name" as "STAGE1-PG-DB" under the "environments" tag using the powershell.
Any help on this is much appreciated.
{
"id": 516,
"environments": [
{
"id": 4598,
"releaseId": 516,
"name": "STAGE1-PG-DB",
"status": "notStarted",
},
{
"id": 4599,
"releaseId": 516,
"name": "STAGE2-PG-DB",
"status": "notStarted",
},
{
"id": 4600,
"releaseId": 516,
"name": "STAGE3-PG-DB",
"status": "notStarted",
}
]
}
I believe you are asking to get the JSON array object where the name is "STAGE1-PG-DB".
Based on the info you've provided, you would do something like this (see my in-line comments)
$releaseDefinitions = Get-Content -Path $inputFileName -Raw | ConvertFrom-Json
# use dot-notation to get the entire Environments array
# pipe the array through using the pipe character
# filter through the array where the key (Name) is equal to your value (STAGE1-PG-DB)
$releaseDefinitions.environments | Where-Object {$_.name -eq "STAGE1-PG-DB"}

Powershell - Create array of arrays for Google sheets append api

I am tryign to use this google sheets append api to update values in bulk. I've used it the past for single rows updates and thats been fine , but i have a large data set I want to append in chunks. Using the
https://sheets.googleapis.com/v4/spreadsheets/$MYSHEETID/values/ExternallyExposed!A1%3AB10:append?insertDataOption=INSERT_ROWS&responseValueRenderOption=UNFORMATTED_VALUE&valueInputOption=RAW
Using the API explorer this is the expected JSON that google expects, note that Values is an array of arrays. Im having difficulty with the values array of arrays section. I cant seem to get it to just be
values : [ [a,b],[c,d],[e,f] ]
i just keep getting something like values : [a,b], values: [c,d]
{
"majorDimension": "ROWS",
"range": "ExternallyExposed!A1:B10",
"values": [
[
"a",
"b"
],
[
"e",
"f"
],
[
"g",
"h"
]
]
}
I've tried various things like
$x = #(
,#("a","b"),
,#("c","D"),
,#("e","F")
) | convertto-json does not produce the expected results.
or
$values= #()
$values+= [pscustomobject]#{
values = #(
"data"
"data"
)
}
gives me
{
"values": [
"data",
"data",
"data"
]
},
{
"values": [
"data",
"data",
"data"
]
}
]
I got help elsewhere, just posting the answer incase others have the same issue.
$values = ("a","b"),("c","d"),("e","f")
$build = [PSCustomObject]#{
'majorDimension' = 'ROWS'
'range' = 'ExternallyExposed!A1:B10'
'values' = $values
}
$json = $build | ConvertTo-Json
The values can also be built this way iterating though a loop.
foreach ($item in $items)
{
$values += ,("a","b")
}

Powershell - Update .JSON

I need some pointers on how to update values in my .json file. Here is a sample fruits.json that I have:
[
{
"ExpireDate": "",
"Origin": "",
"FruitName": "Apple"
},
{
"Expiredate": "",
"Origin": "",
"FruitName": "Orange"
}
]
I have another .JSON file call fruitdetail.json serving as an input file. I need to update the above fruits.json with the info from fruitdetail.json. Basically, lookup the "Fruit Name" from fruitdetail.json and update both "Origin" and "Expire date" keys in fruits.json. Below is what I am starting out with but it doesn't look right.
$fruits = (Get-Content -Path "C:\temp\fruits.json" | ConvertFrom-Json)
$fruitDetail = (Get-Content -Path "C:\temp\fruitdetail.json" | ConvertFrom-Json)
$json = foreach ($fruit in $fruits) {
If ($fruit.FruitName = $fruitDetail.FruitName) {
$Fruit.Origin = $FruitDetail.Origin
$Fruit.ExpireDate = $FruitDetail.ExpireDate
}
}
$json.update
Thanks in advance.
UPDATE: Updated the above code
You're trying to relate data using a common field, similar to an SQL Join. Presumably the fruit name in can be used in this case and for demonstration purposes. Not sure this is perfect, but it should demonstrate the concept.
# Establish Test Date
$JSON_Fruit =
#"
[
{
"Expire Date": "",
"Origin": "",
"Fruit Name": "Apple"
},
{
"Expire date": "",
"Origin": "",
"Fruit Name": "Orange"
}
]
"# |
ConvertFrom-Json
# Establish Test Date
$JSON_FruitDetail = #{}
(#"
[
{
"Expire Date": "10/27/2020",
"Origin": "California",
"Fruit Name": "Apple"
},
{
"Expire date": "11/10/2020",
"Origin": "Arizona",
"Fruit Name": "Orange"
}
]
"# |
ConvertFrom-Json) |
ForEach-Object{
$JSON_FruitDetail.Add( $_.'Fruit Name', $_ )
}
ForEach( $Fruit in $JSON_Fruit )
{
$Fruit."Expire Date" = $JSON_FruitDetail[$Fruit.'Fruit Name']."Expire Date"
$Fruit.Origin = $JSON_FruitDetail[$Fruit.'Fruit Name'].Origin
}
$JSON_Fruit
Note: The parenthesis are to avoid a problem in PowerShell versions prior to 7 (both Windows and Core) In PowerShell 7+ you don't need to use them. For more info see this answer and this one .
Basically you're converting the JSON into PSCustom objects via ConvertFrom-Json. Then storing one side of the data in a dictionary collection keyed on the common field, in this example the "Fruit Name". Then we're looping through the object collection using the "Fruit Name" to reference the entry in the hash table and make the assignment to the destination object's properties.
Note: I've seen a number of PowerShell functions in the community with names like Join-Object that may also be suitable for this, but I usually use techniques like above.

Parsing JSON array with PowerShell

I'm having issues returning specific data from an API query with PowerShell. I'm making a simple API call to grab a user which works great.
$Response = Invoke-RestMethod -uri $uri -Method GET -Headers $Headers
$Response
The call returns the following.
Total Sum Users Groups
----- ----- ----- ------
1 1 #{123456789=} #{Test Users=System.Object[]; Global Users=System.Object[]...
$Response.Users returns the following
123456789
---------
#{name= Test Case; fullname=Test Tester Case; office=Area 51;....
The issue is the number "123456789" is a unique identifier that changes with every user. In order to pull the needed data from each user I need to be able to parse and grab just that number.
Here is the JSON output from $Response.Users
{
"123456789": {
"name": "Test Case",
"fullname": "Tester Test Case",
"office": "Area 51",
"country": "United States",
"groups": [
"Test Users",
"Global Users",
"Test OU"
]
}
}
Any help is greatly appreciated!
Thanks
You can access the name of the note property using the default powershell property PsObject and retrieve the name of it:
$json =
#'
{
"123456789": {
"name": "Test Case",
"fullname": "Tester Test Case",
"office": "Area 51",
"country": "United States",
"groups": [
"Test Users",
"Global Users",
"Test OU"
]
}
}
'#
$json | ConvertFrom-Json | ForEach-Object {$_.PsObject.Properties.Name}
Or in your case:
$Response.Users | ConvertFrom-Json | ForEach-Object {$_.PsObject.Properties.Name}
Should do the trick ;-)

PowerShell : retrieve JSON object by field value

Consider JSON in this format :
"Stuffs": [
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
In PowerShell 3, we can obtain a list of Stuffs :
$JSON = Get-Content $jsonConfigFile | Out-String | ConvertFrom-Json
Assuming we don't know the exact contents of the list, including the ordering of the objects, how can we retrieve the object(s) with a specific value for the Name field ?
Brute force, we could iterate through the list :
foreach( $Stuff in $JSON.Stuffs ) {
But I am hopeful there exists a more direct mechanism ( similar to Lync or Lambda expressions in C# ).
$json = #"
{
"Stuffs":
[
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
}
"#
$x = $json | ConvertFrom-Json
$x.Stuffs[0] # access to Darts
$x.Stuffs[1] # access to Clean Toilet
$darts = $x.Stuffs | where { $_.Name -eq "Darts" } #Darts
I just asked the same question here: https://stackoverflow.com/a/23062370/3532136
It has a good solution. I hope it helps ^^.
In resume, you can use this:
The Json file in my case was called jsonfile.json:
{
"CARD_MODEL_TITLE": "OWNER'S MANUAL",
"CARD_MODEL_SUBTITLE": "Configure your download",
"CARD_MODEL_SELECT": "Select Model",
"CARD_LANG_TITLE": "Select Language",
"CARD_LANG_DEVICE_LANG": "Your device",
"CARD_YEAR_TITLE": "Select Model Year",
"CARD_YEAR_LATEST": "(Latest)",
"STEPS_MODEL": "Model",
"STEPS_LANGUAGE": "Language",
"STEPS_YEAR": "Model Year",
"BUTTON_BACK": "Back",
"BUTTON_NEXT": "Next",
"BUTTON_CLOSE": "Close"
}
Code:
$json = (Get-Content "jsonfile.json" -Raw) | ConvertFrom-Json
$json.psobject.properties.name
Output:
CARD_MODEL_TITLE
CARD_MODEL_SUBTITLE
CARD_MODEL_SELECT
CARD_LANG_TITLE
CARD_LANG_DEVICE_LANG
CARD_YEAR_TITLE
CARD_YEAR_LATEST
STEPS_MODEL
STEPS_LANGUAGE
STEPS_YEAR
BUTTON_BACK
BUTTON_NEXT
BUTTON_CLOSE
Thanks to mjolinor.
David Brabant's answer led me to what I needed, with this addition:
x.Stuffs | where { $_.Name -eq "Darts" } | Select -ExpandProperty Type
Hows about this:
$json=Get-Content -Raw -Path 'my.json' | Out-String | ConvertFrom-Json
$foo="TheVariableYourUsingToSelectSomething"
$json.SomePathYouKnow.psobject.properties.Where({$_.name -eq $foo}).value
which would select from json structured
{"SomePathYouKnow":{"TheVariableYourUsingToSelectSomething": "Tada!"}
This is based on this accessing values in powershell SO question
. Isn't powershell fabulous!
In regards to PowerShell 5.1 ...
Operating off the assumption that we have a file named jsonConfigFile.json with the following content from your post:
{
"Stuffs": [
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
}
This will create an ordered hashtable from a JSON file to help make retrieval easier:
$json = [ordered]#{}
(Get-Content "jsonConfigFile.json" -Raw | ConvertFrom-Json).PSObject.Properties |
ForEach-Object { $json[$_.Name] = $_.Value }
$json.Stuffs will list a nice hashtable, but it gets a little more complicated from here. Say you want the Type key's value associated with the Clean Toilet key, you would retrieve it like this:
$json.Stuffs.Where({$_.Name -eq "Clean Toilet"}).Type
It's a pain in the ass, but if your goal is to use JSON on a barebones Windows 10 installation, this is the best way to do it as far as I've found.
This is my json data:
[
{
"name":"Test",
"value":"TestValue"
},
{
"name":"Test",
"value":"TestValue"
}
]
Powershell script:
$data = Get-Content "Path to json file" | Out-String | ConvertFrom-Json
foreach ($line in $data) {
$line.name
}