Can anyone help me using bash
and jq
to be able to filter this JSON down to only the first occurrence of the user.login
for each item, with the highest submitted_at
key. An endpoint is giving me back historical information and I only want the most up to date details for the response. Take for example this JSON
[
{
"user": {
"login": "user1",
},
"state": "CHANGE_REQUESTED",
"submitted_at": "2024-01-23T19:18:31Z",
},
{
"user": {
"login": "user1",
},
"state": "DISMISSED",
"submitted_at": "2024-02-05T16:49:58Z",
},
{
"user": {
"login": "user1",
},
"state": "APPROVED"
"submitted_at": "2024-02-06T19:18:31Z",
},
{
"user": {
"login": "user2",
},
"state": "APPROVED"
"submitted_at": "2024-01-23T19:18:31Z",
},
{
"user": {
"login": "user2",
},
"state": "DISMISSED"
"submitted_at": "2024-01-21T19:18:31Z",
}
]
The result should be the following JSON with only the most recent duplicate of user.login
that I can then loop over
[
{
"user": {
"login": "user1",
},
"state": "APPROVED"
"submitted_at": "2024-02-06T19:18:31Z",
},
{
"user": {
"login": "user2",
},
"state": "APPROVED"
"submitted_at": "2024-01-23T19:18:31Z",
}
]
After which I can loop through in bash to gather the information that I need from the object.
This may be answered already somewhere but I think I’m struggling to word the ask in a search engine to be able to get the desired result.
2
Answers
In order to result in the JSON that I was expecting, I used the following jq statement.
jq '. |= sort_by(.submitted_at) | reverse | unique_by(.user.login)' "$tmp_response_file_pr_reviews_request"
This sorted the resulting array by it's
submitted_at
revered so that the highest date is at the top, and then usingunique_by
to filter down to only the first instance of each `user.login Key-Value pair in the array, resulting in what I needed.With
group_by(.user.login)
you can group together into subarrays all objects with the same.user.login
value. Then, from each subarray, pick the one item with the highest.submitted_at
value usingmax_by(.submitted_at)
. The final array can be created either using an array constructor[…]
and iterating over the groups using.[]
, or by re-using the grouping array and accessing the groups using amap
.Demo