Reputation: 902
I'm having trouble parsing a JSON file from which I would like to extract elements that does not contains the string "To Do" as label.
Here is the file I'm trying to parse
[
{
"id": 1,
"title": "Task A",
"labels": [
"Low",
"To Do"
]
},
{
"id": 2,
"title": "Task B",
"labels": [
"Medium",
"Done"
]
},
{
"id": 3,
"title": "Task C",
"labels": [
"High",
"To Do"
]
}
]
I can successfully extract elements which contains "To Do" with the following command :
$ cat tmp.json | jq 'keys[] as $k | select(.[$k].labels[] | contains("To Do")) | "\(.[$k].id) -- \(.[$k].title) -- \(.[$k].labels)"'
"1 -- Task A -- [\"Low\",\"To Do\"]"
"3 -- Task C -- [\"High\",\"To Do\"]"
However when I negate the condition jq has the following behaviour :
$ cat tmp.json | jq 'keys[] as $k | select(.[$k].labels[] | contains("To Do") | not) | "\(.[$k].id) -- \(.[$k].title) -- \(.[$k].labels)"'
"1 -- Task A -- [\"Low\",\"To Do\"]"
"2 -- Task B -- [\"Medium\",\"Done\"]"
"2 -- Task B -- [\"Medium\",\"Done\"]"
"3 -- Task C -- [\"High\",\"To Do\"]"
The only difference here is the condition's negation, but all three elements are printed and the one I want to filter is printed twice.
Thanks.
Upvotes: 3
Views: 1605
Reputation: 50815
Your query seems overcomplicated for such a trivial task (I didn't debug but you're probably misusing contains
there; I suspect it's run for each array element, not just once for the array itself).
Anyway, here is a clean and straightforward approach:
.[] | select(.labels | index("To Do") | not) | "\(.id) -- \(.title) -- \(.labels)"
Upvotes: 6
Reputation: 117027
I'd go with all(_; . != "To Do")
:
.[]
| select( all(.labels[]; . != "To Do"))
| "\(.id) -- \(.title) -- \(.labels)"
Upvotes: 3