Reputation: 1071
I'd like to change a value in a JSON file. Following is a snippet of the JSON document that shows the structure I'm trying to traverse:
{
"panels": [
{
"panels": [
{
"alert": {
"notifications": [
{
"uid": "dmRej73Gz"
}
]
}
}
]
}
]
}
What I'd like to change
I'd like to change the value for all UIDs inside of the notifications array to another value.
I have tried the following, with no success:
cat MyJson.json | jq -r '.panels[] |.panels[].alert | .notifications[] | .uid |="newvalue"'
{
"uid": "newvalue"
}
cat MyJson.json | jq -r '. | select(.panels[].panels[].alert.notifications[].uid="newvalue")'
(Note UID not changed at all)
{
"panels": [
{
"panels": [
{
"alert": {
"notifications": [
{
"uid": "dmRej73Gz"
}
]
}
}
]
}
]
}
This is what I'd actually like to see:
{
"panels": [
{
"panels": [
{
"alert": {
"notifications": [
{
"uid": "newvalue"
}
]
}
}
]
}
]
}
Use Case I have Grafana dashboard that I am trying to incorporate into our CICD process. One dashboard will be created in the Dev environment and then deployed to INT and PROD.
The only thing that changes from one environment to the next is the notification channel which is (unfortunately) represented as a UID. I'm making a call to the destination Grafana site and getting the notification UID for the target environment. This will be used as an argument to the JQ call I'm making (what was called newvalue above). Then another JQ call will be made to change the dashboard UID. Then I'll take this modified JSON and post it to the target Grafana environment using the Grafana API.
If all goes well the dashboard will be created with the notification channels intact and with a unique dashboard UID. Hope that's not TMI. :)
Any ideas?
Upvotes: 0
Views: 465
Reputation: 44275
An alternative to @hobbs solution where we use walk()
to change literally all the .uid
values so we don't have to define the full path:
walk(if type == "object" and has("uid") then .uid = "NEW VALUE" else . end)
Also, to remove the unnecessary cat
we can pass the file to JQ itself:
jq 'walk(if type == "object" and has("uid") then .uid = "NEW VALUE" else . end)' MyJson.json
Upvotes: 3
Reputation: 240759
You're overcomplicating:
jq '.panels[].panels[].alert.notifications[].uid |= "newvalue"'
You don't want to drill down and change .
(the scope for what will eventually be output), so the entire path from the top should be on the left side of the |=
operator, and you don't need any |
. There's no need for the -r
option either.
Upvotes: 3