--- title: "jq is a powerful JSON processor" date: 2021-06-13 categories: [ blog ] tags: [unix, jq, json, cli, guide, tinker] --- So lately I've been using `jq` quite a bit. It is a CLI JSON processor that makes your life easier if you have to deal with a lot of JSON. Here I'm going to give two examples of how it's used. ## Search response I've been dealing with JSON from Elasticsearch API[^0], but as they would not release their documents under a free license, I will take an example from OpenSearch instead[^1]: ```json { "took": 39, "timed_out": false, "_shards": { "total": 68, "successful": 68, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 5837, "relation": "eq" }, "max_score": 7.8623476, "hits": [ { "_index": "new_shakespeare", "_type": "_doc", "_id": "100763", "_score": 7.8623476, "_source": { "type": "line", "line_id": 100764, "play_name": "Troilus and Cressida", "speech_number": 43, "line_number": "3.1.68", "speaker": "PANDARUS", "text_entry": "Sweet queen, sweet queen! thats a sweet queen, i faith." } }, { "_index": "shakespeare", "_type": "_doc", "_id": "28559", "_score": 5.8923807, "_source": { "type": "line", "line_id": 28560, "play_name": "Cymbeline", "speech_number": 20, "line_number": "1.1.81", "speaker": "QUEEN", "text_entry": "No, be assured you shall not find me, daughter," } } ] } } ``` Woah that's long! How do you know how much time it took? I want to measure the performance. ```sh $ curl ... | jq '.took' 39 ``` Nice. Not very helpful, though---I can easily see that at the top of the result. I want to see which responses were returned. ```sh $ curl ... | jq '.hits.hits' [ { "_index": "new_shakespeare", "_type": "_doc", "_id": "100763", "_score": 7.8623476, "_source": { "type": "line", "line_id": 100764, "play_name": "Troilus and Cressida", "speech_number": 43, "line_number": "3.1.68", "speaker": "PANDARUS", "text_entry": "Sweet queen, sweet queen! thats a sweet queen, i faith." } }, { "_index": "shakespeare", "_type": "_doc", "_id": "28559", "_score": 5.8923807, "_source": { "type": "line", "line_id": 28560, "play_name": "Cymbeline", "speech_number": 20, "line_number": "1.1.81", "speaker": "QUEEN", "text_entry": "No, be assured you shall not find me, daughter," } } ] ``` The response is the value of `hits` inside a `hits`, so the query is `.hits.hits`. How intuitive! But this is hard to read. Let's just take the `play_name` of the result. ```sh $ curl ... | jq .hits.hits[]._source.play_name "Troilus and Cressida" "Cymbeline" ``` Neat! But how does it work? The brackets `[]` signifies that we should take all the results, from each of which the value for `._source.play_name` is taken. There might be the option to write that in the search query DSL, which also reduces the data transferred, but I bet this is much easier to write. ## Wallpaper I use `feh` for setting wallpaper, which can take an image from the internet. Previously, I used a static list that I collected myself, but I recently discovered a wallpaper API from [wallhaven](https://wallhaven.cc/help/api). Let's say, I want to get a space image as wallpaper, I would use this command: ```sh curl -s 'https://wallhaven.cc/api/v1/search?q=space&ratios=16x9&sorting=toplist' ``` Where `q` is the query, `ratios` is the image ratio so that it fits the screen, and `sorting` is the way the results would be sorted before pagination. The results is long, but it looks like this: ```json { "data": [ { "id": "l3zmwy", "url": "https://wallhaven.cc/w/l3zmwy", "short_url": "https://whvn.cc/l3zmwy", "views": 67050, "favorites": 705, "source": "https://www.artstation.com/artwork/YaQwgP", "purity": "sfw", "category": "general", "dimension_x": 1920, "dimension_y": 1080, "resolution": "1920x1080", "ratio": "1.78", "file_size": 781731, "file_type": "image/jpeg", "created_at": "2021-05-18 19:26:23", "colors": [ "#424153", "#000000", "#663300", "#996633", "#999999" ], "path": "https://w.wallhaven.cc/full/l3/wallhaven-l3zmwy.jpg", "thumbs": { "large": "https://th.wallhaven.cc/lg/l3/l3zmwy.jpg", "original": "https://th.wallhaven.cc/orig/l3/l3zmwy.jpg", "small": "https://th.wallhaven.cc/small/l3/l3zmwy.jpg" } }, ... ] } ``` So, to get the image path from this, I run: ```sh curl ... | jq -r .data[].path | shuf -n 1 | feh --bg-center ``` I use `shuf` because I'd like a new wallpaper every time I run this script. Put this as the startup script or add a cron job and you'll have a changing wallpaper. Disclaimer: this script does not always work, because of `feh`. If you're using GNOME, for example, `feh` can't be used to set background. [^0]: Yes I know it's no longer free software (it still partially is I think). I have no choice, and I would still be more at peace with a source available software that is self-hostable. [^1]: Copyright 2021 OpenSearch contributors. Released under Apache License.