$ curl -s 'https://ip-ranges.amazonaws.com/ip-ranges.json' | jq -r '[path(..)|map(if type=="number" then "[]" else tostring end)|join(".")|split(".[]")|join("[]")]|unique|map("."+.)|.[]'
.
.createDate
.ipv6_prefixes
.ipv6_prefixes[]
.ipv6_prefixes[].ipv6_prefix
.ipv6_prefixes[].network_border_group
.ipv6_prefixes[].region
.ipv6_prefixes[].service
.prefixes
.prefixes[]
.prefixes[].ip_prefix
.prefixes[].network_border_group
.prefixes[].region
.prefixes[].service
.syncToken
(except I have it aliased to "jq-structure" locally of course. also, if there's a new fancy way to do this, I'm all ears; I've been using this alias for like... almost a decade now :/) ~ echo '[path(..)|map(if type=="number" then "[]" else tostring end)|join(".")|split(".[]")|join("[]")]|unique|map("."+.)|.[]' | ~/go/bin/jqfmt -ob -ar -op pipe
[
path(..) |
map(if type == "number" then "[]" else tostring end) |
join(".") |
split(".[]") |
join("[]")
] |
unique |
map("." + .) |
.[]%
~
Not bad! Shame that jqfmt doesn't output a newline at the end, though. The errant `%` is zsh's partial line marker. Also, `-ob -ar -op pipe` seems like a pretty good set of defaults to me - I would prefer that over it (seemingly?) not doing anything with no flags. (At least for this sample snippet.)
But as an example of about where I'd stop using jq/shell scripting and switch to an actual program... we have a service that has task queues. The number of queues for an endpoint is variable, but enumerable via `GET /queues` (I'm simplifying here of course), which returns e.g. `[0, 1, 2]`. There was a bug where certain tasks would get stuck in a non-terminal state, blocking one of those queues. So, I wanted a simple little snippet to find, for each queue, (1) which task is currently executing and (2) how many tasks are enqueued. It ended up vaguely looking like:
which ends up producing output like (assuming queue 0 was blocked)
I think this is roughly where I'd start to consider "hmm, maybe a proper script would do this better". I bet the equivalent Python is much easier to read and probably not much longer.
Although, I think this example demonstrates how I typically use jq, which is like a little multitool. I don't usually write really complicated jq.