クライアント側でjsonファイルの書き出し/読み込みを行う

# はじめに
クライアント側(JavaScript)で連想配列をjson形式のファイルに書き出し、読み込みする方法を簡単に書きたいと思います。
今回クライアント側はJavaScript(Vue.js。UIライブラリとしてVuetify)を使用しています。

## 実装イメージ

見た目のイメージはこんな感じです。
ボタンの色などは別ファイルで設定しているので今回は省略しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/a96acb4e-6176-b17b-013e-893a1be55cf0.png)
ファイルの書き込み、読み込みボタンがあり、
書き込みボタンを押すと、jsonファイルがダウンロード
読み込みボタンを押すと、ファイル選択画面がブラウザで開き、ファイルを選択できる。
*ファイル選択後の処理は今回は書いていません

## 実装全体

```vuejs:example.vue
<template>
  <div class="example">
   <v-row justify="end">
      <!-- 書き出しボタン -->
      <v-col cols="6">
        <v-btn color="primary" outlined block @click="dataExport">書き出し</v-btn>
      </v-col>

      <!-- 読込ボタン -->
      <v-col cols="6">
        <v-btn id="inportBtn" color="primary" @click="btnClick">読み込み</v-btn>
        <input
          type="file"
          style="display: none"
          @change="dataImport"
          ref="input"
          accept="application/json"
        />
      </v-col>
    </v-row>
  </div>
</template>

<script>
  export default {
    data: () => ({
      exampleData: [ // jsonファイルに書き出ししたいデータ
      {
		"name": "太郎",
		"age": 3
	  },
	  {
		"name": "花子",
		"age": 5
	   }]
    }),
    methods: {
      dataExport() {
        const blob = new Blob([JSON.stringify(this.exampleData, null, '  ')], {
          type: 'application/json',
        });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = 'exportData.json'; // 出力するファイルの名前
        link.click();
        link.remove();
      },
      dataImport() {
        const ref: any = this.$refs.input;
        // 選択したファイル
        const file = ref.files[0];
        console.log(file);

        // 何かエラーチェックを行う場合は以下に

        // その他処理(API呼ぶなど)
      },
      btnClick() {
        // 中にあるinput要素を取得
        const ref: any = this.$refs.input;
        // dataImportを実行
        ref.click();
      },
  }
</script>
```

### 解説
##### 実装の部分に記載したコードの一部を読み込みボタンについてと、書き込みボタンについての部分に再度載せています。

- 読み込みボタンについて

```vuejs:example.vue

   ... 省略 ...
  <!-- 読込ボタン -->
    <v-col cols="6">
      <v-btn id="inportBtn" color="primary" @click="btnClick">読み込み</v-btn>
        <input  
          type="file"
          style="display: none"
          @change="dataImport"
          ref="input"
          accept="application/json"
        />
   ... 省略 ...
 <script>
  export default {
     省略 ...
    }),
    methods: {
      dataImport() {
        const ref: any = this.$refs.input;
        // 選択したファイル
        const file = ref.files[0];
        console.log(file);

        // 何かエラーチェックを行う場合は以下に

        // その他処理(API呼ぶなど)
      },
      btnClick() {
        // 中にあるinput要素を取得
        const ref: any = this.$refs.input;
        // dataImportを実行
        ref.click();
      },
  }
</script>
```

btn要素とは別にinput要素を配置。ボタンをクリックすると、
btnClick()が呼ばれ、その中でbtn要素の中のinput要素にアクセス。
アクセスしたinput要素のclick(=dataImport())を呼ぶ と言った流れになります。

今回はファイルアップロードのボタンにcssを付けたかったので、上のような実装にしましたが、
下のシンプルなファイル選択ボタンでいい場合は以下のコードで十分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/c5af6336-2e68-78f0-3e1c-066509b0910e.png)

```vuejs
<input type="file" accept="application/json">
```


- 書き込みボタンについて

```vuejs:example.vue
   ... 省略 ...
  <!-- 書き出しボタン -->
    <v-col cols="6">
      <v-btn color="primary" outlined block @click="dataExport">書き出し</v-btn>
    </v-col>
   ... 省略 ...
 <script>
  export default {
    data: () => ({
      exampleData: [ // jsonファイルに書き出ししたいデータ
      {
		"name": "太郎",
		"age": 3
	  },
	  {
		"name": "花子",
		"age": 5
	   }]
    }),
    methods: {
      dataExport() {
        // JSON.stringifyで文字列に変換
        const blob = new Blob([JSON.stringify(this.exampleData, null, '  ')], {
          type: 'application/json',
        });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = 'exportData.json'; // 出力するファイルの名前
        link.click();
        link.remove();
      },
  }
</script>
```
書き出しボタンを押すとdataExport()が呼ばれます。
今回書き出す対象のデータはdataにあるexampleDataを使っています。
URL.createObjectURLで、blobに対してアクセスができるURLを作成しています。
このURLはブラウザを閉じるまでメモリに残ってしまうので、最後に.removeを使って、削除しています。

このボタンをクリックすると、ブラウザはexportData.jsonというファイルがダウンロードされます。