~huyngo/huyngo.srht.site

f5f00b800f4158aeef28f73407e2064b29113ac3 — Ngô Ngọc Đức Huy a month ago 687e078
Update blog
1 files changed, 204 insertions(+), 0 deletions(-)

A content/posts/2021-06-13-jq.md
A content/posts/2021-06-13-jq.md => content/posts/2021-06-13-jq.md +204 -0
@@ 0,0 1,204 @@
---
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.