クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【JSON】外部JSONファイル化したはっぴいえんどアルバム情報をFetch APIでDOMに読み込む

JSON未遂事件簿」の続きです。 JSON(ジェイソン)はJSの連想配列(オブジェクト)とよく似たとても馴染深いデータ形式。
前回はっぴいえんどアルバム情報を多次元配列にしてDOMに読み込みました。 今回はこれを外部JSONファイル化してFetch APIで読み込んでみます。

※目次:

※参考:連想配列とは

JSONとは

JSONとは「JavaScript Object Notation」の略。以前 、オブジェクトはプロパティとメソッドでできていると説明しましたが、これは狭義の意味で、広義では「配列」も「連想配列」もオブジェクトの一種です。Notationは「表記法」という意味でJSONは「ジャバスクリプトのオブジェクトの表記法」とうい意味です。

前回」の最後に触れたように、JSONはJSの多次元配列とよく似ています。

//多次元配列
var 連想配列名 = {
    キー: 値, 
    キー: {
        キー: 値, キー: 値, キー: 値
     }, 
    キー: 値
};

//JSON
 {
    "キー": 値, 
    "キー": {
        "キー": 値, "キー": 値, "キー": 値
     }, 
    "キー": 値
};

違うのはキーにもダブルコーテーション" "で囲うことと、シングルコーテーション' 'がNGなことです。

※参考:JSON (JavaScript Object Notation)の書式、エンコーディング、MIME Type について

はっぴいえんどの多次元配列をJSON化する

前回作成したはっぴいえんどアルバム情報の多次元配列をJSON化するとこうなります。

[
{
  "title": "はっぴいえんど",
  "release": "1970/8/5",
  "track": [
    "春よ来い",
    "かくれんぼ",
    "しんしんしん",
    "飛べない空",
    "敵タナトスを想起せよ!",
    "あやか市の動物園",
    "12月の雨の日",
    "いらいら",
    "",
    "はっぴいえんど",
    "続はっぴ-いいえ-んど"
  ]
},
{
  "title": "風街ろまん",
  "release": "1971/11/20",
  "track": [
    "抱きしめたい",
    "空いろのくれよん",
    "風をあつめて",
    "暗闇坂むささび変化",
    "はいからはくち",
    "はいから・びゅーちふる",
    "夏なんです",
    "花いちもんめ",
    "あしたてんきになあれ",
    "颱風",
    "春らんまん",
    "愛餓を"
  ]
},
{
  "title": "HAPPY END",
  "release": "1973/2/25",
  "track": [
    "風来坊",
    "氷雨月のスケッチ",
    "明日あたりはきっと春",
    "無風状態",
    "さよなら通り3番地",
    "相合傘",
    "田舎道",
    "外はいい天気",
    "さよならアメリカさよならニッポン"
  ]
}
]

変数albumsには入れず、キーtitlereleasetrackもダブルコーテーション" "で囲いました。
あと、ななんとJSONにはコメントを含むことはできないようです!!削除しました。

※参考:https://www.nxworld.net/tips/use-comment-in-json.html

さあ、完成したJSONデータをファイルとして保存しましょう。JSONの拡張子は.jsではなく.jsonです。今回はhappyend.jsonというファイル名にしました。 これをサーバ上にアップします。/jsonなどわかりやすいディレクトリ名をつけるといいでしょう。*1

非同期通信:Ajaxとは

JSONファイルから読み込んだデータを使ってページの一部(=DOM)のみを変更します。

※参考:DOMとは

ページ全体をリロードせずページの一部のみを変更する技術を「Ajax(エイジャックス)」と言います。Ajaxは「Asynchronous Javascript+XML」の略です。2005年、Ajaxを使ったGoogleマップが登場し、世のWebクリエイターに衝撃を与えました(ページリロードせずに地図のスクロールや拡大縮小ができた)。

XMLは「Extensible Markup Language」の略でExtensibleは「拡張可能」という意味です。Markup LanguageはHTMLのMLと一緒で「マークアップ言語」。全体で「拡張可能なマークアップ言語」という意味になります。XMLはHTMLのような決まったタグ名ではなく独自のタグを作ることができます。これがデータを扱うのに向いています。
Ajaxという言葉ができた2005年頃のデータはXMLが主流でした。現在はJSONの方が主流になってきていますが、言葉としてはXMLの「X」が残り続けているわけです。

Ajaxの中で一番重要な単語は頭の「Asynchronous」で「非同期な」という意味です。XMLをざっくり「データ」と意訳するとAjaxは「ジャバスクリプトとデータによる非同期通信」といった意味になります。非同期通信によってページ全体ではなく必要最低限のデータ読み込みになるためユーザーの操作が快適になるわけです。

※参考:初心者目線でAjaxの説明 - Qiita

JSONを読み込む方法(XMLHttpRequest()、$.getJSON()、$.ajax()、Fetch API)

JSONファイルを読み込む方法はいくつかあります。

  • XMLHttpRequest()
  • jQuey:$.getJSON()、$.ajax()
  • Fetch API

2005年当初は「XMLHttpRequest()」メソッドしか方法がありませんでした。記述量はとても多いです。しかしながら一つ一つを見ていくと、データ読み込み時に何が行われているのかより深く理解できそうです。なお、名前に「XML」とありますがこれは命名時の事情で、実際にはJSONファイルも読み込むことができます。

※参考:XMLHttpRequest についてのメモ - Qiita

次のjQueryの登場によってAjaxは革命的に扱いやすくなりました。jQueryでは「$.getJSON()」と「$.ajax()」の2つのメソッドがあり、$.ajax()の方がより簡潔です!

※参考:【超簡単】jQueryでJSONを読み込む方法【コピペOK】 | マコブログ

最後の「Fetch API」は最近生JSに標準で加わった書き方です。jQeuryほどではないにしてもXMLHttpRequest()に比べるとかなりシンプルになってきたようです。「Fetch」は取ってくる、読んでくる、といった意味で、APIは「Application Programming Interface」。 プログラムでアプリを操作するためのインターフェイス(接点)、といった意味です。

※参考:https://blog.codecamp.jp/api

今回はこのFetch APIを試してみたく思います。

Fetch APIの書式

Fetch APIはこのような書式です。

fetch(URL).then(function(response) {
  return response.text();
}).then(function(text) {
  //処理
});

※参考:お疲れさまXMLHttpRequest、こんにちはfetch - Qiita

いつものように外側から紐解いてみましょう。

fetch(URL).then(処理).then(処理);
  • fetch ()メソッドのあとにthen()メソッドが数珠つなぎになっていてjQueryのメソッドチェーンのようです。
  • fetch ()メソッドの引数にはjsonファイルのURLが、2つのthen()メソッドの引数には処理が書かれます。
fetch(URL).then(function(引数) {
  //処理
}).then(function(引数) {
  //処理
});
  • then()メソッドの引数の中には共に無名関数が入っています。

※参考:無名関数とは

fetch(URL).then(function(response) {
  return response.データ型();
}).then(function(データ型) {
  //処理
});
  • 1つ目のthen()の無名関数の引数はresponseオブジェクトが入ります。
  • この無名関数のブロックには戻り値でresponseオブジェクトのデータ型を指定するメソッドが入ります。
  • データ型でBlob, ArrayBuffer, JSON, Textが指定できます。
  • 2つ目のthen()の無名関数の引数は上のthen()の戻り値のデータ型が入ります。
  • このデータ型に変換されたデータがブロックの中の処理に使われます。

冒頭のコードはresponse.text()でtext型のデータに変換されます。

Fetch APIではっぴいえんどのjsonファイルを読み込む

JSONファイルのデータをFetch APIで読み込んでみます。
ボタンをクリックするとアラートではっぴいえんどのアルバム情報が表示されます!

コードはこうなります。

//jsonファイルURL
var url = 'http://xxx.com/happyend.json';

//ボタン
var btn = document.querySelector('#btn');

//イベント
btn.addEventListener('click', function() {

  //json読み込み
  fetch(url)
    .then(function(response) {
      return response.text();
    })
    .then(function(text) {
      //アラート
      alert(text);
    });

}, false);
  • 変数urlにjsonファイルのURLを入れます
  • 変数btnにダミーで作ったid#btnのDOMを紐づけています。
  • btnのクリックイベントをイベントリスナを設定
  • イベントの中にFetch APIを入れる。引数はjsonファイルのURL。
  • 1つ目のthen ()text形式の戻り値を返す。
  • 2つ目のthen()でアラートでtextを表示。

※参考:イベントリスナとは

ボタンを押すと値(1stアルバムタイトル)だけ表示

先ほどのアラートはデータ全体がそのまま表示されていました。中の値を一つ一つ取り出せるとより実用的です。
先ほどのコードはテキスト形式text()で読み込みましたが、値を読むにはJSON形式json()にします。

fetch(URL).then(function(response) {
  return response.json();
}).then(function(json) {
  オブジェクト.プロパティ = json[キー];
});
  • 1つ目のthen()の戻り値のtext()json()に変更
  • 2つ目のthen()の無名関数の引数にjsonをいれる。
  • 処理をしたいオブジェクトにjsonを代入し[キー]でキーの値を呼び出す。

※参考:javascript fetch APIでjsonデータを取得する - Symfoware

ボタンをクリックすると「押すが良い」のテキストが1stアルバムのタイトル「はっぴいえんど」に変わります!

//クリックイベントの中
  fetch(url)
    .then(function(response) {
      return response.json();
    })
    .then(function(json) {
      //1stアルバムのタイトル
      btn.innerHTML = json[0]["title"];
    });
  • 最初の例text()json()に変更
  • json[0]["title"]で、jsonファイル内の1つ目の配列(1stアルバム)のタイトルtitleの値を呼び出す。
  • innerHTMLでボタンのテキストがタイトルの値に変更される

アルバム情報全部を表示する

データを値単位で取り出せたので、「前回」のコードを改造して外部JSONファイルのはっぴいえんどアルバム情報全部を表示できそうですね。さっそくやってみます!!

できました!「前回」と全く同じ形ではっぴいえんどのアルバム情報を表示しています!コードはこのようになります。

<h1 class="bandname">はっぴいえんど</h1>
<div class="spec">
  <section class="album">
    <h2 class="title"></h2>
    <p class="release"></p>
    <ol class="track"></ol>
  </section>
</div>
</section>

まず、HTMLは前回と全く同じです。JSがちょっと違います。

//jsonファイルURL
var url = 'http://xxx.com/happyend.json';

//json読み込み
  fetch(url)
    .then(function(response) {
      return response.json();
    })
    .then(function(json) {

    //外枠アクセス
    var spec = document.querySelector('.spec');

    //テンプレ複製
    //(アルバム枚数-1枚)
    for (var i=1; i < json.length; i++) {
      var clone = spec.firstElementChild.cloneNode(true);
      spec.appendChild(clone);
    }
    
    //タイトル、発売日、曲名アクセス
    var specTitle = document.querySelectorAll('.title');
    var specRelease = document.querySelectorAll('.release');
    var specTrack = document.querySelectorAll('.track');
    
    //アルバムデータ入力(アルバム枚数分)
    for (var i=0; i < json.length; i++) {  
      //タイトル入力
      specTitle[i].innerHTML = json[i].title;
      //発売日入力
      specRelease[i].innerHTML = json[i].release;
      //曲名入力(曲数分ループ)
      for(var t=0; t < json[i].track.length; t++) {
        var list = document.createElement('li');
        list.innerHTML= json[i].track[t];
       specTrack[i].appendChild(list);        
      }
    }
  });
  • 前回、冒頭に多次元配列で直接書いてあったはっぴいえんどのアルバム情報は今回は変数urlで外部JSONファイル化しています。
  • 先ほどのコードにあったクリックイベントは削除しています。(クリックではなくページ読み込みと同時に実行)
  • fetch().then().then() の部分はそのままです。データ形式も引き続きjson()です。
  • 2つ目のthen()の中に前回のコードを入れています(詳しくは前回参照)が、一部を書き換えています。
  • 前回のアルバム情報を入れていた変数albumsの部分をjsonに書き換えています。これによって変数albumsではなく外部JSONファイルに値を読みにいくわけです。

最後に

本当は前回の投稿でここまでたどり着きたかったのですが、あまりに前提知識が少なかったため、ここまでかかってしまいました。*2

やったことは

  • HTMLのタグとテキストを分離
  • テキストをJS内でデータ化
  • データをJSから外部JSONファイルに分離
  • JSONファイルの読み込み

です。単なるテキストから再利用性、拡張性の高いデータに生まれ変わったと思います!

今、自分がブログで並行して進めているコンテンツは最終的にJSONデータ連携に繋がっていきそうな予感がしており、大きな一歩を踏めたと思っています。
それではまた!


※参考:ネイティブJSやってみたシリーズ
qiita.com

*1:CodePenはSSL(https:〜)上のファイルじゃないとブロックしたため今回はDropboxにあげています

*2:7月13日の金曜日にJSONネタをアップしたかったので、1ヶ月以上かかったことになります(笑)