I am a newbie to powershell, and I am trying to create function that copies an object from a json data, creates new object from it and assigns different values to the max parameter. So far, different versions of my implementation assigns only the last value from an array $ParameterValues
to all the new objects created.
One solution, might be probabbly be to read the json data using a call by reference [ref]$jsonData
. However, I am not even sure that is a thing in powershell.
--- Here is the sample json file:
"algorithms": {
"obj0": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 7
}
}
--- Function Select-Member
helps select the object to copy
function Select-Member {
[CmdLetBinding()]
param(
[Parameter(Mandatory)]
[string]$Path,
[Parameter(Mandatory)]
[Object]$InputParameter
)
Write-Debug $InputParameter
$Path -split '/' | ForEach-Object { $selected = $InputParameter } { $selected = $selected.$_ } { $selected }
}
--- Function Set-Member
pastes the new object
copied using Select-Member
or overwrites the values of the parameter
selected
function Set-Member {
[CmdletBinding()]
param(
[Object]$Value,
[string[]]$Path,
[Object]$Object
)
$Head, $Next, $Tail = $Path
if (($null -eq $Next) -or (1 -gt $Next.Length)) {
Add-Member -Passthru -Force -MemberType NoteProperty `
-Input $Object -Name $Head -Value $Value
}
else {
Add-Member -Passthru -Force -MemberType NoteProperty `
-Input $Object -Name $Head `
-Value (Set-Member -Value $Value -Path ([string[]]$Next + $Tail) -Object ($Object.$Head))
}
}
--- test-func
function uses Select-Member
to select an object (obj0
for example), then Set-Member
adds new copies (obj1
, obj2
, obj3
) of the object selected and then it should assign a new value to Max
iteratatively from $ParameterValues
array.
function test-func {
[CmdletBinding()]
param (
[Parameter(Mandatory, Position)]
[string] $ObjectSelect,
[Parameter(Mandatory, Position)]
[string] $Parameter,
[Parameter(Mandatory, Position)]
[Object[]] $ParameterValues
)
$PathToPaste = ($ObjectSelect -Split '/', -2)[0] -Split '/'
$JsonData = Get-content "$JSON_FILE" -raw | convertFrom-Json
$ObjectSelected = Select-Member $ObjectSelect $JsonData
[string]$NewObjName
foreach ($ele in $ParameterValues){
$NewObjName = "obj" + $ele
Set-Member $ObjectSelected $NewObjName $JsonData.$PathToPaste
$PathToParameter = $PathToPaste, $NewObjName, $Parameter-Split'/'
Set-Member $ele $PathToParameter $JsonData
}
$JsonData | ConvertTo-Json -depth 32 | set-content "$JSON_FILE"
}
When I run the following command for example, test-func -ObjectSelect algorithms/obj0 -Parameter parameters/max -ParameterValues 1,2,3
to iteratatively assign each value from the $ParameterValues
to max
, it sets only the last value from the array to all the new objects created, obj1
, obj2
, obj3
.
Here is the results I get. (Observe that the value max
in the last three objects (obj1
, obj2
, obj3
) are all identical = 3.
"algorithms": {
"obj0": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 7
}
},
"obj1": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 3
}
},
"obj2": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 3
}
},
"obj3": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 3
}
}
}
The expected results should be like this (Observe that the value of max
are 1, 2, 3 for the last three objects (obj1
, obj2
, obj3
) respectively.):
"algorithms": {
"obj0": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 7
}
},
"obj1": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 1
}
},
"obj2": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 2
}
},
"obj3": {
"command": "...",
"parameters": {
"min": 2.7,
"max": 3
}
}
}
As of now, the only solution I have is using the following for-each
loop in the test-func` function, which is definitely not professional. Notice it saves and reads again the json file on line 4 and 5. Like I said I am sure this is not professional as it will take up memory and time.
foreach ($ele in $ParameterValues){ $NewObjName = "obj" + $ele Set-Member $ObjectSelected $NewObjName $JsonData.$PathToPaste $JsonData | ConvertTo-Json -depth 32 | set-content "$JSON_FILE" $JsonData = Get-content "$JSON_FILE" -raw | convertFrom-Json $PathToParameter = $PathToPaste, $NewObjName, $Parameter-Split'/' Set-Member $ele $PathToParameter $JsonData }