ネストした json のキーを辿る

elasticsearch の API のレスポンスみたいな、深くネストした json は俯瞰で見づらいので、フラットにして眺めるための手順。
あるいは jq の `--stream` オプションの使い方。

## 元のjson

ここから拝借。
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html

```json:a.json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.3862944,
    "hits": [
      {
        "_index": "twitter",
        "_type": "_doc",
        "_id": "0",
        "_score": 1.3862944,
        "_source": {
          "user": "kimchy",
          "message": "trying out Elasticsearch",
          "date": "2009-11-15T14:12:12",
          "likes": 0
        }
      }
    ]
  }
}
```

## キーを辿る

ついでに leaf node を抽出。

```bash
$ cat a.json | jq -c --stream 'select(length==2)'
[["took"],1]
[["timed_out"],false]
[["_shards","total"],1]
[["_shards","successful"],1]
[["_shards","skipped"],0]
[["_shards","failed"],0]
[["hits","total","value"],1]
[["hits","total","relation"],"eq"]
[["hits","max_score"],1.3862944]
[["hits","hits",0,"_index"],"twitter"]
[["hits","hits",0,"_type"],"_doc"]
[["hits","hits",0,"_id"],"0"]
[["hits","hits",0,"_score"],1.3862944]
[["hits","hits",0,"_source","user"],"kimchy"]
[["hits","hits",0,"_source","message"],"trying out Elasticsearch"]
[["hits","hits",0,"_source","date"],"2009-11-15T14:12:12"]
[["hits","hits",0,"_source","likes"],0]
```

## key をフラットにする

```bash
$ cat a.json | jq -c --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}'
{"key":"took","value":1}
{"key":"timed_out","value":false}
{"key":"_shards.total","value":1}
{"key":"_shards.successful","value":1}
{"key":"_shards.skipped","value":0}
{"key":"_shards.failed","value":0}
{"key":"hits.total.value","value":1}
{"key":"hits.total.relation","value":"eq"}
{"key":"hits.max_score","value":1.3862944}
{"key":"hits.hits.0._index","value":"twitter"}
{"key":"hits.hits.0._type","value":"_doc"}
{"key":"hits.hits.0._id","value":"0"}
{"key":"hits.hits.0._score","value":1.3862944}
{"key":"hits.hits.0._source.user","value":"kimchy"}
{"key":"hits.hits.0._source.message","value":"trying out Elasticsearch"}
{"key":"hits.hits.0._source.date","value":"2009-11-15T14:12:12"}
{"key":"hits.hits.0._source.likes","value":0}
```

## 全体を1階層に寄せる

いったん1件ずつ出力したのをパイプに流して `jq --slurp` で受けるのがコツ。

```bash
$ cat a.json | jq --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}' | jq -s from_entries
{
  "took": 1,
  "timed_out": false,
  "_shards.total": 1,
  "_shards.successful": 1,
  "_shards.skipped": 0,
  "_shards.failed": 0,
  "hits.total.value": 1,
  "hits.total.relation": "eq",
  "hits.max_score": 1.3862944,
  "hits.hits.0._index": "twitter",
  "hits.hits.0._type": "_doc",
  "hits.hits.0._id": "0",
  "hits.hits.0._score": 1.3862944,
  "hits.hits.0._source.user": "kimchy",
  "hits.hits.0._source.message": "trying out Elasticsearch",
  "hits.hits.0._source.date": "2009-11-15T14:12:12",
  "hits.hits.0._source.likes": 0
}
```

## おまけ：1行ずつ出力して [fuzzy finder](https://github.com/junegunn/fzf) に流すとか

```bash
$ cat a.json | jq -c --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}' | fzf
```