Accessing values in a PS custom object property generated from JSON - json

For a JSON like this:
{
"Tours": [{
"Code": "r",
"Name": "Tour 1",
"Tournaments": [{
"Number": "464",
"Title": "Open Tournament 1"
},
{
"Number": "047",
"Title": "Open Tournament 2"
}]
},
{
"Code": "s",
"Name": "Tour 2",
"Tournaments": [{
"Number": "524",
"Title": "Tournament 3"
},
{
"Number": "009",
"Title": "Tournament 4"
}]
}]
}
when converted to a PS custom object and saved in $data variable, I can access values under 'Tournaments' for specific 'Tours' like this:
$data.Tours[0].Tournaments
$data.Tours[1].Tournaments
But, is it possible to access 'Tournaments' properties and values by specifying 'Code' or 'Name' values under 'Tours'? Something like that, maybe:
$data.Tours.Code['r'].Tournaments
Actually, in a PS script I want to filter data by 'Code' under 'Tours' and get underlying 'Tournaments' (get 'Tournaments' for specific 'Code' of the 'Tours').

You would need to do something like:
$data.Tours | Where-Object { $_.Code -eq 'r' } | Select-Object -ExpandProperty 'Tournaments'
To get the list of concatenated codes and tournament numbers (where the code is "r") you could do:
$data.Tours | Where-Object { $_.Code -eq 'r' } | ForEach-Object { $Code = $_.Code; $_.Tournaments | ForEach-Object { $Code + $_.Number }}

Related

(PowerShell) How to remove double quotes from the JSON output?

Here's an excerpt from my PowerShell script, that writes JSON data to a file:
$jsonData = #"
{
"FunctionName" :
{
"description": "",
"parameters": [],
"signature" : ""
}
}
"#
$jsonParameterData = #"
{
`t`t`t`t`t`t`t`t`t`t"description": "",
`t`t`t`t`t`t`t`t`t`t"name": ""
`t`t`t`t`t`t`t`t`t }
"#
$jsonData = $jsonData | ConvertFrom-Json
In the code above I have defined the JSON template that I will use to write to the file. I'm using jsonData to describe the function FunctionName with the keys of description, parameters, and signature.
On the other hand, I'm using jsonParameterData to describe each argument of the function FunctionName with the keys of description and name.
My PowerShell script pulls the data from other files, and writes this JSON information to a .json file.
For example, if the signature of the function I want to extract data from is Function FunctionName(Parameter1, Parameter2), in the .json file I would expect to see this:
"FunctionName": {
"description": "This function does this and that",
"parameters": [
{
"description": "This is the first parameter",
"name": "Parameter1"
},
{
"description": "This is the second parameter",
"name": "Parameter2"
}
],
"signature": "Function FunctionName(Parameter1, Parameter2)"
}
Somewhere in the code, I store the number of function arguments in the variable NumberOfArguments; the arguments of the function in ArrayOfArguments, and the argument descriptions in ArrayOfArgumentDescriptions.
The PowerShell code below is used to add jsonParameterData to jsonData:
for($i=0; $i -lt $NumberOfArguments; $i++){
$SelectedArgument = $ArrayOfArguments[$i]
$SelectedDescription = $ArrayOfArgumentDescriptions[$i]
$jsonData.AplusWait.parameters += $jsonParameterData
}
Then, I write jsonData to the file like this:
$jsonData = $jsonData | ConvertTo-Json | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }
$jsonData.Substring(1, $jsonData.length - 2) | Add-Content -Path $OutputFile
Write-Output "`nFinished writing JSON data to file.`n"
However, the resulting output slightly does not match the intended output. The output looks like this:
"FunctionName": {
"description": "This function does this and that",
"parameters": [
"{
"description": "This is the first parameter",
"name": "Parameter1"
}",
"{
"description": "This is the second parameter",
"name": "Parameter2"
}"
],
"signature": "Function FunctionName(Parameter1, Parameter2)"
}
If you look closely, the output displays the parameters array as an array of strings (note the double quotes), when it should actually be an array of JSON objects.
How can I transform this:
"{
"description": "This is the first parameter",
"name": "Parameter1"
}"
into this:
{
"description": "This is the first parameter",
"name": "Parameter1"
}
?
Having the following JSONs:
$jsonData = #"
{
"foo": {
"des": "foo-des",
"par": [],
"sig": "foo-sig"
}
}
"#
$jsonParamData = #"
{
"des": "param-des",
"name": "param-name"
}
"#
$jsonObj = $jsonData | ConvertFrom-Json
$jsonParamObj = $jsonParamData | ConvertFrom-Json
# add param
$jsonObj.foo.par += $jsonParamObj
# Pay attention to the -Depth parameter otherwise the final json will be truncated
$jsonResult = $jsonObj | ConvertTo-Json -Depth 5
Write-Host $jsonResult
Should print:
{
"foo": {
"des": "foo-des",
"par": [
{
"des": "param-des",
"name": "param-name"
}
],
"sig": "foo-sig"
}
}
When converting objects back to json you should pay attention to the -Depth parameter since it will truncate your result.

Need to search a text file for a string and capture a second string located after the first

I'm working with an API call and I need to parse the JSON returned by the API in PowerShell. I'm searching for a particular name and then I need to capture a another item that follows it.
$json = #"
{
"Test": [
{
"association": "(None)",
"description": "",
"displayName": "BusIntel48.png",
"galleryImage": "[PlugIn]Images;Trebuchet.PlugIn.Images.Images.Common.BusIntelligence.BusIntel48.png",
"id": "944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56",
"links": [],
"localizedScopeName": "Built in",
"name": "BusIntel48.png",
"parentFolder": "ImagesCommonBusIntelligence",
"parentIsScopeFolder": false,
"scope": "FromResource",
"scopeOwner": "",
"standInKey": "DefType:ImageDef#Scope:FromResource#Id:944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56"
},
{
"association": "(None)",
"description": "",
"displayName": "BusProcActOnEvent16.png",
"galleryImage": "[PlugIn]Images;Trebuchet.PlugIn.Images.Images.Common.BusIntelligence.BusProcActOnEvent16.png",
"id": "944f73cc5cb33339be6db84987baef3f7190c931cf",
"links": [],
"localizedScopeName": "Built in",
"name": "BusProcActOnEvent16.png",
"parentFolder": "ImagesCommonBusIntelligence",
"parentIsScopeFolder": false,
"scope": "FromResource",
"scopeOwner": "",
"standInKey": "DefType:ImageDef#Scope:FromResource#Id:944f73cc5cb33339be6db84987baef3f7190c931cf"
}
]
}
"#
$x = $json | ConvertFrom-Json
$name = $x.Test | where { $_.name -eq "BusIntel48.png" }
I need to search for the name of the image file (ex. "name": "BusIntel48.png") and then capture the string after "standInKey: (ex. DefType:ImageDef#Scope:FromResource#Id:944f73cc5c1a812eaa2ade43bd9ca0c9a40f963c56).
Just need a change in last line.
You can also select one property by using :
$name = $x.Test | where { $_.name -eq "BusIntel48.png" } | Select-Object -Property "standInKey"

Amending Existing JSON Files in Powershell 4

I have seen many questions around this however none of the answers seem to work (please correct me if i am wrong)
I have created a function that queries an API and saves the result as a json file.
However I would like to amend the file that is saved
powershell code:
$search = ""
function searchMtgApi($searchName){
$uriSafeName = [uri]::EscapeDataString($searchName)
$res = Invoke-WebRequest "https://api.magicthegathering.io/v1/cards?name=$uriSafeName" -UseBasicParsing
$resJson = $res.content | ConvertFrom-Json
$resJson.cards | Format-Table
$resJson.cards | Select name, setName, "quantity" | ConvertTo-Json | Out-File "D:\Magic the Gathering\$searchName.json"
}
while ($search -ne "exit"){
Write-Host #'
To exit, type "Exit".
'#
$search = Read-Host "Search Magic the Gathering.IO by card name"
if($search -ne "exit"){
searchMtgApi $search
}
}
Json generated (searching for the card 'Ponder')
[
{
"name": "Ponder",
"setName": "Commander 2018",
"quantity": null
},
{
"name": "Ponder",
"setName": "Lorwyn",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic 2010",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic 2012",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic Player Rewards 2008",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic Online Promos",
"quantity": null
}
]
What I would like to do is load the file and amend the "quantity" for a particular set.
Can anyone point me in the right direction?
Update -
I will get the json content from a file:
function updateJsonFile($jsonfile){
$resJson = Get-Content "$jsonfile.json" | ConvertFrom-Json
#Edit Quantity here
$resJson | ConvertFrom-Json | Format-Table
}
Focusing just on the core question, with abridged sample input:
The following selectively updates the quantity property for an object with a given setName property value, converting from and to JSON:
$setName = 'Magic 2010' # the set name of interest
$newQuantity = 42 # new quantity
(#'
[
{
"name": "Ponder",
"setName": "Commander 2018",
"quantity": null
},
{
"name": "Ponder",
"setName": "Lorwyn",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic 2010",
"quantity": null
}
]
'# | ConvertFrom-Json) |
ForEach-Object {
if ($_.setName -eq $setName) {
$_.quantity = $newQuantity
}
$_ # pass the (possibly updated) object through.
} | ConvertTo-Json
Note the need to enclose the ConvertFrom-Json call in (...), which forces enumeration of the individual objects in the array constructed from the JSON input (see this answer for background information).
The above yields (note the updated last quantity value):
[
{
"name": "Ponder",
"setName": "Commander 2018",
"quantity": null
},
{
"name": "Ponder",
"setName": "Lorwyn",
"quantity": null
},
{
"name": "Ponder",
"setName": "Magic 2010",
"quantity": 42
}
]
Applied to your updateJsonFile function:
function updateJsonFile($jsonfile, $setName, $newQuantity){
$resJson = Get-Content "$jsonfile.json"
# Note the (...) around the ConvertFrom-Json command.
($resJson | ConvertFrom-Json) |
ForEach-Object {
if ($_.setName -eq $setName) {
$_.quantity = $newQuantity
}
$_ # pass the (possibly updated) object through.
} | ConvertTo-Json | Set-Content -Encoding Utf8 $jsonfile
}

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'

Select a node from a JSON file that matches a property value

I am having a json object stored in a variable. From the json object, I want to fetch the node which matches a value. For example - an item having machineId 12.
My json looks like
{
"items": [
{
"id": "asdasd",
"machineId": "12",
"placementGroup": "",
"region": "158",
"staticIp": "",
"staticIpAction": "",
"subnetIDs": [
]
},
{
"id": "asdasd",
"machineId": "43",
"placementGroup": "",
"region": "158",
"staticIp": "",
"staticIpAction": "",
"subnetIDs": [
]
}
]
}
Load the json using the Get-Content cmdlet and convert it to json using the ConvertFrom-Json cmdlet. Select the items node and filter it by the desired machineId using the Where-Object cmdlet:
Get-Content 'yourPathToYour.json' |
ConvertFrom-Json |
Select-Object -ExpandProperty items |
Where-Object machineId -eq 12
Output:
id : asdasd
machineId : 12
placementGroup :
region : 158
staticIp :
staticIpAction :
subnetIDs : {}