jsonといえばajaxで受け取ってフロントでゴニョゴニョするデータというイメージだったのですが、ローカルから読み込んでフロントだけで扱うこともできるんですね。割と最近知って色々使い所ありそうだなと思ったのでメモっておこうと思います。

FileReaderを使う

ざっくりとサンプルを作ってみました。PC内jsonファイルを選択すると、そのファイルの中身を表示するというものです。ソースコードはこちら。

<input type="file" id="file">
<div id="result">ここに結果が表示されます</div>
window.onload = () => {
  const file = document.getElementById('file');
  const result = document.getElementById('result');
  //  FileReaderオブジェクトを生成
  const reader = new FileReader();

  // ファイルが選択されたらFileReaderオブジェクトにファイルをテキストとして保存
  file.addEventListener('change', function(e){
    reader.readAsText(e.target.files[0]);
  });

  // ファイルの読み込みが終わったら内容を表示
  reader.onload = function(e){
    result.innerText = e.target.result;
  };
};

サンプルはこちら↓

See the Pen フロントだけでローカルのjsonファイルを読み込む by diwao (@diwao) on CodePen.

ポイントはFileReaderオブジェクト。これを使うことでユーザのPC内にあるファイルをWebから非同期的に読み込むことができるようになります。

処理の概要

大体の流れはコード内のコメントに書いた通りなのですが、もう少し細かい部分について分解して説明してみたいと思います。

input要素からFileオブジェクトを取得

// ファイルが選択されたらFileReaderオブジェクトにファイルをテキストとして保存
file.addEventListener('change', function(e){
  reader.readAsText(e.target.files[0]);
});

ここでは、input要素に対してchangeイベントを設定しています。input要素の値が変わったら、すなわちファイルが何か選択されたら何らかの処理を実行するというものですね。

で、実際に実行している処理がこちら↓

reader.readAsText(e.target.files[0]);

ここで出てくるe.targetとはつまりinput要素のことで、e.target.filesはFileListオブジェクトを意味します。FileLIstオブジェクトにはユーザーが選択したファイルを示すFileオブジェクトが含まれており、複数ファイルを選択していればそれらを一気に扱うこともできるようです。

今回は1ファイルしか選択しない想定なので、Fileオブジェクトがひとつという前提でe.target.files[0]とし、FileListオブジェクトの最初のデータとしてFileオブジェクトを取得しています。そうやって取得したFileオブジェクトをFileReaderのreadAsTextメソッド渡しているというのがこの部分の処理でした。

ちなみに、大体お察しかと思いますがreadAsTextメソッドは読んで字のごとくファイルの内容を文字列として保存するメソッドです。

ファイル読み込み時の処理にはonloadを使う

// ファイルの読み込みが終わったら内容を表示
reader.onload = function(e){
  result.innerText = e.target.result;
};

ここではファイルの読み込みが終わったら、その内容を表示するといった処理をしています。

FileReader.onloadに設定した処理はファイルの読み込みが成功したときに発火します。読み込みが完了したときというのはつまり先ほど説明したreadAsTextメソッドの処理が完了したらということですね。

また、この関数の中のe.targetは変数readerを指しているので、e.target.resultはFileReaderオブジェクトのresultプロパティということになります。resultプロパティはファイルの読み込みが終了したあとに有効となるもので、ここではreadAsTextメソッドの結果、つまりファイルの内容を文字列として格納しています。

なので、それをdomのinnerTextに代入すればファイルの中身を画面上に表示できるというわけです。

jsonファイルならデータとして扱うことも可

読み込んだファイルをjsonファイルであれば、readAsTextメソッドでテキスト化したデータをJSON.parseすることで自由に扱うことも可能です。読み込んだデータをサーバに送信すればインポート機能みたいなものも作れたりするでしょうし、色々と応用が利きそうな気がします。

参考