Reputation: 1742
I have some data in JSON which I want to edit using JQ.
mobile
.mobile
has a number
(which is obviously unique) and no. of calls
made.total
calls (sum of calls for each mobile they have)I have tried to use self explanatory variables here. Please let me know if the data is not clear enough.
[
{
"name": "Person1",
"mobiles": [{
"number": "11111",
"calls": 2
},{
"number": "22222",
"calls": 3
}],
"total": 5
},
{
"name": "Person2",
"mobiles": [{
"number": "33333",
"calls": 1
},{
"number": "44444",
"calls": 2
},{
"number": "55555",
"calls": 1
}],
"total": 4
}
]
What I want is, given a mobile number and no. of calls made for that mobile on a particular day, update the json (update both the individual counter and the total)
Eg. Let's say for number 444444
calls made are 5, then the final json should be
[
{
"name": "Person1",
"mobiles": [{
"number": "11111",
"calls": 2
},{
"number": "22222",
"calls": 3
}],
"total": 5
},
{
"name": "Person2",
"mobiles": [{
"number": "33333",
"calls": 1
},{
"number": "44444",
"calls": 7 // previous value was 2, added 5 more
},{
"number": "55555",
"calls": 1
}],
"total": 9 // previous total was 4, added 5 more
}
]
I am able to update the total
calls but not the individual calls for the given number
map(select(.mobiles[].number == "44444").total = .total + 5)
gives
[
{
"name": "Person1",
"mobiles": [
{
"number": "11111",
"calls": 2
},
{
"number": "22222",
"calls": 3
}
],
"total": 5
},
{
"name": "Person2",
"mobiles": [
{
"number": "33333",
"calls": 1
},
{
"number": "44444",
"calls": 2 // How do I update this
},
{
"number": "55555",
"calls": 1
}
],
"total": 9 // This is correct
}
]
Upvotes: 2
Views: 418
Reputation: 116670
To update the relevant "calls" along the lines you were exploring:
map( (.mobiles[] | select(.number == $number) | .calls) += $incr)
where the values of $number and $incr can (for example) be specified on the command line, e.g.
jq --arg number 44444 --argjson incr 5 -f update.jq input.json
To update the relevant "total", you could use any/2
:
map( if any(.mobiles[]; .number == $number)
then .total += $incr
else .
end)
You could chain these two together, either literally, or (presumably more efficiently) by combining the two filters into a single map
. For readability and maintainability, you might also want to define helper functions (i.e., using def
).
Upvotes: 2