json 内の文字列で入ってるjsonの中身を書き換える

# Overview

何を言ってるのかわからねーと思うが（ｒｙ

## 稀によくある状況

kibana の `Visualize` でグラフを設定して、これを保存してどこか他のkibanaに移行したい場合、
`Visualize` は `Index Patterns` に紐付いているので、
そのまま他所に投入しても `Index Patterns` のIDが違うので上手くいかない。

これを `jq` で書き換えてやる方法。

## version

kibana: 6.4.2

とかいいつつ、**kibanaが本題ではないんですけど**。

まぁ細かい話は置いといて、サンプルいきます。

```bash:env
export URL_KIBANA=http://localhost:5601
export VISUALIZATION_ID=27248030-3683-11e9-bf8e-47f2e867c71f
```

# `visualization` のサンプル

```bash
curl "${URL_KIBANA}/api/saved_objects/visualization/${VISUALIZATION_ID}"
```

```json:saved_objects.visualization.json
{
  "id": "27248030-3683-11e9-bf8e-47f2e867c71f",
  "type": "visualization",
  "updated_at": "2019-02-22T09:20:53.683Z",
  "version": 1,
  "attributes": {
    "title": "sample",
    "visState": "{\"title\":\"sample\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}",
    "uiStateJSON": "{}",
    "description": "",
    "version": 1,
    "kibanaSavedObjectMeta": {
      "searchSourceJSON": "{\"index\":\"437ab3b0-3671-11e9-bf8e-47f2e867c71f\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
    }
  }
}
```

これの

* `.attributes.visState`
* `.attributes.kibanaSavedObjectMeta.searchSourceJSON`

が文字列で入ってる箇所で、

## `.attributes.visState`

```bash
jq '.attributes.visState|fromjson' saved_objects.visualization.json
```

```json
{
  "title": "sample",
  "type": "histogram",
  "params": {
    "type": "histogram",
    "grid": {
      "categoryLines": false,
      "style": {
        "color": "#eee"
      }
    },
    "categoryAxes": [
      {
        "id": "CategoryAxis-1",
        "type": "category",
        "position": "bottom",
        "show": true,
        "style": {},
        "scale": {
          "type": "linear"
        },
        "labels": {
          "show": true,
          "truncate": 100
        },
        "title": {}
      }
    ],
    "valueAxes": [
      {
        "id": "ValueAxis-1",
        "name": "LeftAxis-1",
        "type": "value",
        "position": "left",
        "show": true,
        "style": {},
        "scale": {
          "type": "linear",
          "mode": "normal"
        },
        "labels": {
          "show": true,
          "rotate": 0,
          "filter": false,
          "truncate": 100
        },
        "title": {
          "text": "Count"
        }
      }
    ],
    "seriesParams": [
      {
        "show": "true",
        "type": "histogram",
        "mode": "stacked",
        "data": {
          "label": "Count",
          "id": "1"
        },
        "valueAxis": "ValueAxis-1",
        "drawLinesBetweenPoints": true,
        "showCircles": true
      }
    ],
    "addTooltip": true,
    "addLegend": true,
    "legendPosition": "right",
    "times": [],
    "addTimeMarker": false
  },
  "aggs": [
    {
      "id": "1",
      "enabled": true,
      "type": "count",
      "schema": "metric",
      "params": {}
    }
  ]
}
```

## `.attributes.kibanaSavedObjectMeta.searchSourceJSON`

```bash
jq '.attributes.kibanaSavedObjectMeta.searchSourceJSON|fromjson' saved_objects.visualization.json
```

```json
{
  "index": "437ab3b0-3671-11e9-bf8e-47f2e867c71f",
  "query": {
    "query": "",
    "language": "lucene"
  },
  "filter": []
}
```

# 書き換えたい箇所

このうち、 `.attributes.kibanaSavedObjectMeta.searchSourceJSON` の `index` の値を書き換えたい。

なんと `jq` だけでできるんです。

```bash:env
export INDEX_PATTERN_ID=ここを書き換えたい
```

## ややこしいので外部ファイルにします

```js:modify.index_pattern_id.jq
.attributes.kibanaSavedObjectMeta.searchSourceJSON
|= (
  fromjson
  | .index=$ENV.INDEX_PATTERN_ID
  | tojson
)
```

## で、実行すると、

```bash
jq -f modify.index_pattern_id.jq saved_objects.visualization.json
```

```json
{
  "id": "27248030-3683-11e9-bf8e-47f2e867c71f",
  "type": "visualization",
  "updated_at": "2019-02-22T09:20:53.683Z",
  "version": 1,
  "attributes": {
    "title": "sample",
    "visState": "{\"title\":\"sample\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}",
    "uiStateJSON": "{}",
    "description": "",
    "version": 1,
    "kibanaSavedObjectMeta": {
      "searchSourceJSON": "{\"index\":\"ここを書き換えたい\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
    }
  }
}
```

できました。

まぁ **本題は `jq` なので** kibana のjsonとかどうでもいいんですけど。

# jq の機能

流れとしては

* `fromjson` で文字列をパースして
* `index` キーの値を書き換えて
* `tojson` で文字列に戻したもので
* `.attributes.kibanaSavedObjectMeta.searchSourceJSON` の値を上書き

という感じです。

## `fromjson` `tojson`

整形中のjsonを文字列にしたり、jsonとして解釈したりしてくれる[めっちゃイケてるjqのビルトイン](https://stedolan.github.io/jq/manual/v1.5/)です（雑

## `|=`

それ以降に続くコマンドの結果で、対象の値を上書きします。

おわり。

kibana の話はまた別記事で書く。かも。たぶん。