Reputation: 367
I am stuck on how to get key value pairs from a json file dynamically meaning without knowing the key value in advance.
I have this sample json file, in the real application I have about 20 json files with a couple of thousand automated test cases:
{
"runOnMachines": "SERVER-01",
"cases": [
{
"testName": "Google Chrome Install 84.0.4147.89",
"testDescription": "Verifies Google Chrome is Installed 84.0.4147.89",
"testFunction": "Find-ProgramVersion",
"args": [
{
"programName" : "Firefox",
"version" : "79.0"
}
],
"expectedResult": "true"
},
{
"testName": "Tera Term 4.105",
"testDescription": "Tera Term 4.105",
"testFunction": "Find-ProgramVersion",
"args": [
{
"programName" : "Tera Term",
"version" : "4.105"
}
],
"expectedResult": "true"
}
]
}
Find-ProgramVersion is a helper function which searches for a program installed in control panel / programs installed through the registry, it returns true or false. (More info on that here Winster Is part of an automated framework I built to test virtual machines on servers.
Long story short, I have this ugly code, that I am trying to clean up, but I can't find how to extract my args dynamically from a json file. As of now, each function I write on Winster module I have to come on this script and add it manually with the correct json properties.
if($jsonData[$i].testFunction -eq "Find-ProgramVersion")
{
$command = $jsonData[$i].testFunction + " " + $jsonData[$i].args.programName + " " +
$jsonData[$i].args.version
}
if($jsonData[$i].testFunction -eq "Find-ProgramVersionGrep")
{
$command = $jsonData[$i].testFunction + " " + $jsonData[$i].args.programName + " " +
$jsonData[$i].args.version
}
I've tried casting jsonData[$i].args
to array, I've also tried using Name and Value from PsObject.Properties but that gives also other values I don't need inherited from PsObject
for($i=0; $i -lt $jsonData.Count; $i++)
{
$jsonData[$i].args.PSObject.Properties | ForEach-Object {
$_.Name
$_.Value
}
}
Gives me:
Count
1
Length
1
LongLength
1
Rank
1
SyncRoot
programName version
----------- -------
Firefox 79.0
IsReadOnly
False
IsFixedSize
True
IsSynchronized
False
Count
1
Length
1
LongLength
1
Rank
1
SyncRoot
Tera Term 4.105
IsReadOnly
False
IsFixedSize
True
IsSynchronized
False
What I am hoping to get from jsonData[$i].args is some kind of iterable, where I can use forloop, but I haven't been able to make the below PsObject usable. And witthout knowing args names in advance since some functions have different numbers of args.
@{programName=Firefox; version=79.0} @{programName=Tera Term; version=4.105}
Upvotes: 3
Views: 1179
Reputation: 440162
(@'
{
"runOnMachines": "SERVER-01",
"cases": [
{
"testName": "Google Chrome Install 84.0.4147.89",
"testDescription": "Verifies Google Chrome is Installed 84.0.4147.89",
"testFunction": "Find-ProgramVersion",
"args": [
{
"programName" : "Firefox",
"version" : "79.0"
}
],
"expectedResult": "true"
},
{
"testName": "Tera Term 4.105",
"testDescription": "Tera Term 4.105",
"testFunction": "Find-ProgramVersion",
"args": [
{
"programName" : "Tera Term",
"version" : "4.105"
}
],
"expectedResult": "true"
}
]
}
'@ | ConvertFrom-Json).cases | ForEach-Object {
$_.testFunction + ' ' + (
$_.args.ForEach( {
$_.PSObject.Properties.Value.ForEach( {
if ($_.contains(' ')) {
# contains spaces -> double-quote
'"{0}"' -f $_
}
else {
$_
}
})
})
) -join ' '
}
The above returns the following:
Find-ProgramVersion Firefox 79.0
Find-ProgramVersion "Tera Term" 4.105
More work is needed if there are values with embedded "
chars.
$_.args.ForEach
iterates over all elements of the args
array.
$_.PSObject.Properties.Value.ForEach
iterates over all property values of each element.
$_.contains(' ')
tests each property value for the presence of at least one space character, in which case the value is enclosed in double quotes ('"{0}"' -f $_
) in the overall command line that is being constructed (via the string constructed from the space-joined values with -join ' '
).
Upvotes: 5