117

I like to filter json files using jq:

jq . some.json

Given the json containing an array of objects:

{
  "theList": [
    {
      "id": 1,
      "name": "Horst"
    },
    {
      "id": 2,
      "name": "Fritz"
    },
    {
      "id": 3,
      "name": "Walter"
    },
    {
      "id": 4,
      "name": "Gerhart"
    },
    {
      "id": 5,
      "name": "Harmut"
    }
  ]
}

I want to filter that list to only show the elements with id having the value 2 and 4, so the expected output is:

{
  "id": 2,
  "name": "Fritz"
},
{
  "id": 4,
  "name": "Gerhart"
}

How do I filter the json using jq? I have played around with select and map, yet didn't got any of those to work, e.g.:

$ jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json
true
2
  • 22
    Everyone please note: The question is about jq, not jQuery. Commented Jun 30, 2016 at 11:28
  • @T.J.Crowder YMMD ^^ And I clarified in the question :D Commented Jun 30, 2016 at 11:31

4 Answers 4

175

From the docs:

jq '.[] | select(.id == "second")' 

Input [{"id": "first", "val": 1}, {"id": "second", "val": 2}]

Output {"id": "second", "val": 2}

I think you can do something like this:

jq '.theList[] | select(.id == 2 or .id == 4)' array.json
Sign up to request clarification or add additional context in comments.

3 Comments

jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json yields in: true o.O
It's returning the evaluation of both clauses, try this: jq '.theList[] | select(.id == 2 or .id == 4)'
jq '.theList[] | select(.id == 2 or .id == 4)' array.json did the trick, you may update your answer :)
29

You could use select within map.

.theList | map(select(.id == (2, 4)))

Or more compact:

[ .theList[] | select(.id == (2, 4)) ]

Though written that way is a little inefficient since the expression is duplicated for every value being compared. It'll be more efficient and possibly more readable written this way:

[ .theList[] | select(any(2, 4; . == .id)) ]

1 Comment

10

Using select(.id == (2, 4)) here is generally inefficient (see below).

If your jq has IN/1, then it can be used to achieve a more efficient solution:

.theList[] | select( .id | IN(2,3))

If your jq does not have IN/1, then you can define it as follows:

def IN(s): first(select(s == .)) // false;

Efficiency

One way to see the inefficiency is to use debug. The following expression, for example, results in 10 calls to debug, whereas only 9 checks for equality are actually needed:

.theList[] | select( (.id == (2,3)) | debug )

["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
  "id": 2,
  "name": "Fritz"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
  "id": 3,
  "name": "Walter"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]

index/1

In principle, using index/1 should be efficient, but as of this writing (October 2017), its implementation, though fast (it is written in C), is inefficient.

Comments

1

Here is a solution using indices:

.theList | [ .[map(.id)|indices(2,4)[]] ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.