Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

date/numeric filter with jq

Tags:

json

date

filter

jq

I have a json that looks like this (it's the result of simple jq filter):

[{
    "name": "Corrine",
    "firstname": "Odile",
    "uid": "PA2685",
    "roles": [{
            "role_name": "GQ",
            "start": "2012-06-20"
        },
        {
            "role_name": "HOUSE",
            "start": "2012-06-26"
        },
        {
            "role_name": "HOUSE",
            "start": "2017-06-28"
        }
    ]
},
{
    "name": "Blanche",
    "firstname": "Matthieu",
    "uid": "PA2685",
    "roles": [{
            "role_name": "SENATE",
            "start": "2014-06-20"
        },
        {
            "role_name": "SENATE",
            "start": "2012-06-26"
        },
        {
            "role_name": "SENATE",
            "start": "2012-06-28"
        }
    ]
}
]

I would like to filter in two ways:

  • select only the first-level objects that have at least one role_name (inside the roles array) whose value is HOUSE;
  • and from this group select only the ones that have at least one start whose date is in 2017 or after.

In the json above "Corrine Odile" would be the only one selected.

I tried some with_entries(select(.value expressions, but my I'm confused about how to deal with the dates as well as the "at least one" requirement.

like image 929
maqueiouseur Avatar asked Feb 23 '26 14:02

maqueiouseur


1 Answers

Requirements of the form "at least one" can usually be satisfied efficiently using any/2, e.g.

any(.roles[]; .role_name == "HOUSE")

The check for the year can (apparently) be accomplished by:

.start | .[:4] | tonumber >= 2017

Solution

To produce an array of objects satisfying the two conditions:

map(select(
  any(.roles[]; .role_name == "HOUSE") and
  any(.roles[]; .start[:4] | tonumber >= 2017) ))

.start[:4] is short for .start|.[0:4]

like image 72
peak Avatar answered Feb 25 '26 13:02

peak