Select objects based on value of variable in object using jq

Just try this one as a full copy paste in the shell and you will grasp it.

# pass the multiline string to the jq, use the jq to 
# select the attribute named "card_id" 
# ONLY if its neighbour attribute
# named "card_id_type" has the "card_id_type-01" value.
# jq -r means give me ONLY the value of the jq query no quotes aka raw


cat << EOF | \
    jq -r '.[]| select (.card_id_type == "card_id_type-01")|.card_id'
    [  
     { "card_id": "id-00", "card_id_type": "card_id_type-00"},
     { "card_id": "id-01", "card_id_type": "card_id_type-01"},
     { "card_id": "id-02", "card_id_type": "card_id_type-02"}
    ]
EOF
# this ^^^ MUST start first on the line - no whitespace there !!!
# outputs:
# id-01

or with an aws cli command

 # list my vpcs or
 # list the values of the tags which names are "Name" 
 aws ec2 describe-vpcs | jq -r '.| .Vpcs[].Tags[]
        |select (.Key == "Name") | .Value'|sort  -nr

Note that you could move up and down in the hierarchy both during the filtering phase and during the selecting phase :

 kubectl get services --all-namespaces -o json | jq -r '
 .items[] | select( .metadata.name 
     | contains("my-srch-string")) | 
     { name: .metadata.name, ns: .metadata.namespace 
     , nodePort: .spec.ports[].nodePort
     , port: .spec.ports[].port}
 '

To obtain a stream of just the names:

$ jq '.[] | select(.location=="Stockholm") | .name' json

produces:

"Donald"
"Walt"

To obtain a stream of corresponding (key name, "name" attribute) pairs, consider:

$ jq -c 'to_entries[]
        | select (.value.location == "Stockholm")
        | [.key, .value.name]' json

Output:

["FOO","Donald"]
["BAR","Walt"]

I had a similar related question: What if you wanted the original object format back (with key names, e.g. FOO, BAR)?

Jq provides to_entries and from_entries to convert between objects and key-value pair arrays. That along with map around the select

These functions convert between an object and an array of key-value pairs. If to_entries is passed an object, then for each k: v entry in the input, the output array includes {"key": k, "value": v}.

from_entries does the opposite conversion, and with_entries(foo) is a shorthand for to_entries | map(foo) | from_entries, useful for doing some operation to all keys and values of an object. from_entries accepts key, Key, name, Name, value and Value as keys.

jq15 < json 'to_entries | map(select(.value.location=="Stockholm")) | from_entries'

{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

Using the with_entries shorthand, this becomes:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

Adapted from this post on Processing JSON with jq, you can use the select(bool) like this:

$ jq '.[] | select(.location=="Stockholm")' json
{
  "location": "Stockholm",
  "name": "Walt"
}
{
  "location": "Stockholm",
  "name": "Donald"
}

Tags:

Bash

Select

Json

Jq