In the JSON example below how to find all the elements which contain string "Choice" and replace them with another string, for example "Grade". So with below all the fields name "***Choice" should change to "***Grade".
I have pasted the expected output below. Given that I don't know how many fields will have the string "Choice", I don't want to simply do [$in ~> | ** [firstChoice] | {"firstGrade": firstChoice}, ["firstChoice"] | ;]
which is a straight find and replace.
{
"data": {
"resourceType": "Bundle",
"id": "e919c820-71b9-4e4b-a1c8-c2fef62ea911",
"firstChoice": "xxx",
"type": "collection",
"entry": [
{
"resource": {
"resourceType": "Condition",
"id": "SMART-Condition-342",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "38341003",
"display": "Essential hypertension",
"firstChoice": "xxx"
}
],
"text": "Essential hypertension"
},
"clinicalStatus": "active",
"secondChoice": "xxx"
},
"search": {
"mode": "match"
}
}
]
}
}
Expected output
{
"data": {
"resourceType": "Bundle",
"id": "e919c820-71b9-4e4b-a1c8-c2fef62ea911",
"firstGrade": "xxx",
"type": "collection",
"entry": [
{
"resource": {
"resourceType": "Condition",
"id": "SMART-Condition-342",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "38341003",
"display": "Essential hypertension",
"firstGrade": "xxx"
}
],
"text": "Essential hypertension"
},
"clinicalStatus": "active",
"secondGrade": "xxx"
},
"search": {
"mode": "match"
}
}
]
}
}
There might be simpler ways, but this is an expression I came up with in JSONata:
(
$prefixes := $keys(**)[$ ~> /Choice$/].$substringBefore('Choice');
$reduce($prefixes, function($acc, $prefix) {(
$choice := $prefix & "Choice";
$acc ~> | ** [$lookup($choice)] | {$prefix & "Grade": $lookup($choice)}, [$choice] |
)}, $$)
)
It looks terrible, but I'll explain how I built it up anyway.
You started with the expression
$ ~> | ** [firstChoice] | {"firstGrade": firstChoice}, ["firstChoice"] |
which is fine if you only want to replace one choice, and you know the full name. If you want to replace more than one, then you can chain these together as follows:
$ ~> | ** [firstChoice] | {"firstGrade": firstChoice}, ["firstChoice"] |
~> | ** [secondChoice] | {"secondGrade": secondChoice}, ["secondChoice"] |
~> | ** [thirdChoice] | {"thirdGrade": thirdChoice}, ["thirdChoice"] |
At this point, you could create a higher-order function that takes the choice prefix and returns a partial substitution (note that the |...|...|
syntax generates a function). Then you can chain these together for an array of prefixes using the built in $reduce()
higher-order function. So you get something like this:
(
$prefixes := ["first", "second", "third"];
$reduce($prefixes, function($acc, $prefix) {(
$choice := $prefix & "Choice";
$acc ~> | ** [$lookup($choice)] | {$prefix & "Grade": $lookup($choice)}, [$choice] |
)}, $$)
)
But if you don't know the set of prefixes up front, and want to select, say, all property names that end in 'Choice', the the following expression will get you that:
$prefixes := $keys(**)[$ ~> /Choice$/].$substringBefore('Choice')
Which then arrives at my final expression. You can experiment with it here in the exerciser on your data.