「JSON未遂事件簿」の続きです。 JSON(ジェイソン)はJSの連想配列(オブジェクト)とよく似たとても馴染深いデータ形式。
前回はっぴいえんどアルバム情報を多次元配列にしてDOMに読み込みました。 今回はこれを外部JSONファイル化してFetch APIで読み込んでみます。
※目次:
- JSONとは
- はっぴいえんどの多次元配列をJSON化する
- 非同期通信:Ajaxとは
- JSONを読み込む方法(XMLHttpRequest()、$.getJSON()、$.ajax()、Fetch API)
- Fetch APIの書式
- Fetch APIではっぴいえんどのjsonファイルを読み込む
- ボタンを押すと値(1stアルバムタイトル)だけ表示
- アルバム情報全部を表示する
- 最後に
※参考:連想配列とは
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
には入れず、キーtitle
、release
、track
もダブルコーテーション" "
で囲いました。
あと、ななんと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は「ジャバスクリプトとデータによる非同期通信」といった意味になります。非同期通信によってページ全体ではなく必要最低限のデータ読み込みになるためユーザーの操作が快適になるわけです。
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