For context, I am attempting to create a cmdlet that would allow for single value substitutions on arbitrary Json files, for use in some pipelines. I've managed to get this working for non-array-containing Json.
A representative bit of Json:
{"test": {
"env": "dev",
"concept": "abstraction",
"array": [
{"id":1, "name":"first"},
{"id":2, "name":"second"}
]
}
}
I want to be able to replace values by providing a function with a path like test.array[1].name
and a value.
After using ConvertFrom-Json
on the Json above, I attempt to use the following function (based on this answer) to replace second
with third
:
function SetValue($object, $key, $value) {
$p1, $p2 = $key.Split(".")
$a = $p1 | Select-String -Pattern '\[(\d{1,3})\]'
if ($a.Matches.Success) {
$index = $a.Matches.Groups[1].Value
$p1 = ($p1 | Select-String -Pattern '(\w*)\[').Matches.Groups[1].Value
if ($p2.length -gt 0) { SetValue -object $object.$p1[$index] -key $p2 -value $value }
else { $object.$p1[$index] = $value }
}
else {
if ($p2.length -gt 0) { SetValue -object $object.$p1 -key $p2 -value $value }
else {
Write-Host $object.$p1
$object.$p1 = $value
}
}
}
$content = SetValue -object $content -key "test.array[1].name" -rep "third"
Unfortunately this results in the following:
{ "test": {
"env": "dev",
"concept": "abstraction",
"array": [
"@{id=1; name=first}",
"@{id=2; name=third}"
]
}
}
If the values in the array aren't objects the code works fine as presented, it's only when we get to objects within arrays that this output happens.
What would be a way to ensure that the returned Json contains an array that is more in line with the input?
Edit: please note that the actual cause of the issue lay in not setting the -Depth
property of ConvertTo-Json
to 3 or greater. Doing so restored the resulting Json to the expected format. The accepted answer was still helpful in investigating the cause.