'How to check if element exists in array with jq

I have an array and I need to check if elements exists in that array or to get that element from the array using jq, fruit.json:

{
    "fruit": [
        "apple", 
        "orange",
        "pomegranate",
        "apricot",
        "mango"
    ]
}


cat fruit.json | jq '.fruit .apple' 

does not work



Solution 1:[1]

The semantics of 'contains' is not straightforward at all. In general, it would be better to use 'index' to test if an array has a specific value, e.g.

.fruit | index( "orange" )

However, if the item of interest is itself an array, the general form:

 ARRAY | index( [ITEM] )

should be used, e.g.:

[1, [2], 3] | index( [[2]] )  #=> 1

IN/1

If your jq has IN/1 then a better solution is to use it:

.fruit as $f | "orange" | IN($f[])

If your jq has first/1 (as does jq 1.5), then here is a fast definition of IN/1 to use:

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

any(_;_)

Another efficient alternative that is sometimes more convenient is to use any/2, e.g.

any(.fruit[]; . == "orange")

or equivalently:

any(.fruit[] == "orange"; .)

Solution 2:[2]

To have jq return success if the array fruit contains "apple", and error otherwise:

jq -e '.fruit|any(. == "apple")' fruit.json >/dev/null

To output the element(s) found, change to

jq -e '.fruit[]|select(. == "apple")' fruit.json

If searching for a fixed string, this isn't very relevant, but it might be if the select expression might match different values, e.g. if it's a regexp.

To output only distinct values, pass the results to unique.

jq '[.fruit[]|select(match("^app"))]|unique' fruit.json

will search for all fruits starting with app, and output unique values. (Note that the original expression had to be wrapped in [] in order to be passed to unique.)

Solution 3:[3]

[WARNING: SEE THE COMMENTS AND ALTERNATIVE ANSWERS.]

cat fruit.json | jq '.fruit | contains(["orange"])'

Solution 4:[4]

For future visitors, if you happen to have the array in a variable and want to check the input against it, and you have jq 1.5 (without IN), your best option is index but with a second variable:

.inputField as $inputValue | $storedArray|index($inputValue)

This is functionally equivalent to .inputField | IN($storedArray[]).

Solution 5:[5]

Expanding on the answers here, If you need to filter the array of fruit against another array of fruit, you could do something like this:

cat food.json | jq '[.fruit[] as $fruits | (["banana", "apple"] | contains([$fruits])) as $results | $fruits | select($results)]'

This will return an array only containing "apple" in the above sample json.

Solution 6:[6]

This modified sample did worked here:

jq -r '.fruit | index( "orange" )' fruit.json | tail -n 1

It gets only the last line of the output.

If it exist, it returns 0. If don't, it returns null.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 John Kugelman
Solution 4 peak
Solution 5 Ron Sims II
Solution 6