Select objects based on value of variable in object using jq

JsonBashSelectJq

Json Problem Overview


I have the following json file:

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

I am using jq and want to get the "name" elements of the objects where 'location' is 'Stockholm'.

I know I can get all names by

cat json | jq .[] | jq ."name"
"Jack"
"Walt"
"Donald"

But I can't figure out how to print only certain objects, given the value of a sub key (here: "location" : "Stockholm").

Json Solutions


Solution 1 - Json

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"
}

Solution 2 - Json

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"]

Solution 3 - Json

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"
  }
}

Solution 4 - Json

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}
 '

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanielView Question on Stackoverflow
Solution 1 - JsonDanielView Answer on Stackoverflow
Solution 2 - JsonpeakView Answer on Stackoverflow
Solution 3 - JsonspazmView Answer on Stackoverflow
Solution 4 - JsonYordan GeorgievView Answer on Stackoverflow