Had a big deeply-nested JSON blob and needed to find every email field anywhere in it, at any depth. My first instinct was a Python script. Nope.

jq '.. | objects | select(has("email")) | .email' blob.json

The .. is recursive descent. It emits every value in the tree, at every depth. Pipe to objects to filter down to just objects. Then pick out the ones that have the field you want.

Less verbosely:

jq '.. | .email? // empty' blob.json

.email? tries to access .email and produces nothing (rather than an error) if the current thing isn’t an object. // empty swallows nulls. Output is every email found anywhere.

This is hugely useful for poking at API responses whose shape you don’t know yet. “Where does this response put the error message?” “Does anything in this blob have a phone number?”

Combined with paths:

jq 'paths(. == "abc@example.com") | join(".")' blob.json

…which prints the JSON path to every occurrence of a value. “Where in this document does this email appear?”

jq’s documentation is dense. Finding these tricks tends to happen through Stack Overflow archaeology. Writing them down here so I don’t forget.