【JQuery】JSONデータを取得して表示を切り替えるデモ

2015.1.30 jQuery

いまいちよく解っていなかったので調べてみました。

JSONとは?

JSON(ジェイソン)は、「Javascript Object Nation」の略。
データ記述言語の1つで、名前の割にJavascript専用ではなく、さまざまな言語間でのデータの受け渡しに互換性があります。

主に2つの構造を基にしています。

名前/値のペアの集まり。様々な言語で、これはオブジェクト、レコード、構造体、ディクショナリ、ハッシュテーブル、キーのあるリスト、連想配列として実現されています。
値の順序付きリスト。ほとんどの言語で、これは配列として実現されています。

http://www.json.org/json-ja.html

Ajax(googleマップで用いられているようなリアルタイムでデータを受信して受け渡す方法)でよく用いられている「XML」と同じような場面で用いることが出来ますが、
JSONのほうが記法や内容が人間にとって理解しやすいという記事をちらほら見かけたりします。
「XML」と「JSON」の違いはこの記事が解りやすそうです。
XMLとJSONの話(1) データフォーマットとしての比較 – 泥のように

まぁ要するにテキストでいろいろ簡単に出来るよってことです。

JSONの書き方

JSONは

  • null
  • 真偽値
  • 数値
  • 文字列
  • 配列
  • オブジェクト(や、連想配列)

のデータを、文字列で表現できます。

JSONで取り扱える値

改行やダブルクォートを値に入れ込みたい場合は、バックスラッシュでエスケープしてください。
ちなみに、シングルクォートは使うことが出来ません。

Object(オブジェクト)

基本的には「{」から「}」の間に「名前:値」のペアを書き込みます。名前の後には「:(コロン)」を入れてください。
さらにこの値のところにオブジェクトを入れ子にしていくことで細かく分岐できたりします。

JSONの基本的な記法

Array(配列)

配列は「[」で始まり、「]」で終わります。

JSONで配列を書く場合

イメージの参照元:http://www.json.org/json-ja.html

キーと値のセット

[
 { "名前1" : "値1"}
 ]
キーと値のセットを2つ
 [
 {"名前1" : "値1" } ,
 {"名前2" : "値2" } ,
 ]

オブジェクトにキーと値のセットの配列を格納

[
 {
 "配列の名前" : [
 {"名前” : "値" } ,
 {"名前2" : "値2"}
 ] ,
 "配列の名前2" : [
 {"名前” : "値" } ,
 {"名前2" : "値2"}
 ] 
}
]

SublimeTextのキーバインド設定やパッケージのコマンドなんかはこんな感じの書き方ですね。

オブジェクトにキーと値のセットの配列を格納

[
 {
 "配列の名前" : {
 "名前” : "値" ,
 "名前2" : "値2"
 } ,
 "配列の名前2" : {
 "名前” : "値" ,
 "名前2" : "値2"
 }
}
 ]

値だけを指定した配列

["値1" , "値2" , "値3" , "値4"]
この場合は0から始まるキーが自動で割り振られます。
1つの配列オブジェクトに複数のキーと値を格納
[
 {
 "名前1" : "値1" ,
 "名前2" : "値2" ,
 "名前3" : "値3"
 }
 ]

よくある書き方としては以上のような具合です。

JSONをJQueryで取得して表示する

今回はjQueryを使って、JSONデータを取り出してみます。

JSONデータを取り出すためには「$.get()メソッド」を使います。
これはAjax通信を行うためのものです。
jQuery.get( url, data, callback ) – jQuery 日本語リファレンス

getJSONでも可です。
jQuery.getJSON( url, data, callback ) – jQuery 日本語リファレンス

今回は例として、「気になる店舗を選んで情報を表示する」ことを想定して実装ます。
選んだお店の情報が、表に出力されるようにしてみましょう。

サンプルHTML

まず、htmlのselectとoption要素で、お店を選択できるようにします。

                            <select name="shoplist" id="localselect">
                                   <optgroup label="日本">
                                        <option value="tokyo-shibuya" selected>東京 渋谷店</option>
                                        <option value="tokyo-shinjuku">東京 新宿ルミネ店</option>
                                        <option value="tokyo-harajuku">東京 原宿店</option>
                                        <option value="ohsaka">大阪 心斎橋店</option>
                                        <option value="fukuoka">福岡 天神店</option>
                                   </optgroup>
                              </select>

ちなみに「option value=””」(「data-○○=””」でも構いません)が、選択項目を識別するために重要な値となります。

続いて、お店の住所と電話番号を表示するところ。初期値である「渋谷店」の情報を最初に書いておきます。

     <div class="adress">
               <ul>
                    <li class="place">
                         <dl>
                              <dt>Adress</dt>
                              <dd>これは【渋谷店】の住所です。</dd>
                         </dl>
                    </li>
                    <li class="tel">
                         <dl>
                              <dt>Tel</dt>
                              <dd>03-1111-1111</dd>
                         </dl>
                    </li>
               </ul>
     </div>

地図も入れちゃいましょう。

               <div id="mapArea" class="left panel map bg ">
                    <!-- MAP -->
                         <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3241.647512992275!2d139.7044617!3d35.661055200000014!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x60188b5883137c35%3A0x5f2ad800dc869924!2z5p2x5Lqs6YO95riL6LC35Yy65riL6LC377yR5LiB55uu77yR77yR4oiS77yR!5e0!3m2!1sja!2sjp!4v1408274701556" frameborder="0" style="border:0"></iframe>
                    <!-- MAP -->
               </div>

ここまでのコードに軽くCSSを指定してこのようにします。

何もおきないデモ

これだけでは何もおきませんね。

次にJSONファイルを用意します。ここには今回のテーマにそって、お店のデータを書き込んでおくとします。

サンプルJSON

[
 {
 "tokyo-shibuya" : {
 "name" : "渋谷店" ,
 "adress" : "これは【渋谷店】の住所です。" ,
 "telnum" : "03-1111-1111" ,
 "map" : "!1m18!1m12!1m3!1d3241.647512992275!2d139.7044617!3d35.661055200000014!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x60188b5883137c35%3A0x5f2ad800dc869924!2z5p2x5Lqs6YO95riL6LC35Yy65riL6LC377yR5LiB55uu77yR77yR4oiS77yR!5e0!3m2!1sja!2sjp!4v1408274701556"
 },
"tokyo-shinjuku" : {
 "name" : "新宿店" ,
 "adress" : "これは【新宿店】の住所です。" ,
 "telnum" : "03-2222-2222" ,
 "map" : "!1m14!1m8!1m3!1d3240.3557212720593!2d139.70512!3d35.69286299999999!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9eeacd89ba0ae1d2!2zUkFVTSDmlrDlrr_mnKzlupc!5e0!3m2!1sja!2sjp!4v1408280348217"
 },
"tokyo-harajuku" :
 {
 "name" : "原宿店" ,
 "adress" : "これは【原宿店】の住所です。" ,
 "telnum" : "03-3333-3333" ,
 "map" : "!1m18!1m12!1m3!1d1620.6670703475122!2d139.70802010216633!3d35.66877362913186!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x315f81ecf625f8b2!2z44K444Oj44Oz44Od44O844Or44O744Ko44O044Kh44Oz6KGo5Y-C6YGT44OS44Or44K65bqX!5e0!3m2!1sja!2sjp!4v1408274857214"
 },
"fukuoka" :
 {
 "name" : "福岡天神店" ,
 "adress" : "これは【福岡天神店】の住所です。" ,
 "telnum" : "03-4444-44444" ,
 "map" : "!1m14!1m8!1m3!1d3323.4832432553194!2d130.397222!3d33.592763999999995!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x8d8c47783262df33!2z44K144Kk44OQ44OD44Kv5aSp56We5bqX!5e0!3m2!1sja!2sjp!4v1408280889951"
 },
"ohsaka" :
 {
 "name" : "大阪心斎橋" ,
 "adress" : "これは【大阪天神店】の住所です。" ,
 "telnum" : "03-5555-5555" ,
 "map" : "!1m18!1m12!1m3!1d3281.3693711712262!2d135.499719!3d34.67062600000001!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x6000e7117af5b233%3A0xdc1b17ba3232750!2z44Kk44Oz44K_44O844ON44OD44OI44Kr44OV44KnIOOCteOCpOODkOODg-OCr-Wkp-mYquilv-W_g-aWjuapi-W6lw!5e0!3m2!1sja!2sus!4v1408274974093"
 }
 }
 ]

渋谷、新宿、原宿、福岡天神、大阪心斎橋に店舗があるとしましょう。
なかなかですね。

項目を説明します。
まず、各店舗のデータを配列で格納したオブジェクトが「shibuya」や「ohsaka」です。
name」「adress」ときて「telnum」が電話番号ですが、その下の「map」には謎の文字の羅列。
これは、GoogleMapを切り替えるためのものです。

埋込み式のGoogleMapは以下の様なコードですが

<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d3241.6741117494234!2d139.729088!3d35.660399999999996!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x60188b770913970d%3A0xccc3467fcb15b353!2z44Kw44O844Kw44Or5qCq5byP5Lya56S-!5e0!3m2!1sja!2sjp!4v1422176760367" width="600" height="450" frameborder="0" style="border:0"></iframe>

(Google株式会社)
iframe src=”https://www.google.com/maps/embed?pb=」ぐらいまでは共通なのですね(たぶん)。
なので、ファイルをキレイにするために、それ以下の文字列を切り替える形で実装します。

というわけで以上が今回の例でもJSONデータの項目です。
見てわかるとおり、JSONならとても人間が理解しやすい書き方ができます。

では、JSONデータを抽出するjQueryを書きましょう。

サンプルjQuery

ざっと説明すると、JSONデータをループさせて必要な領域に挿入しているだけです。

何をやっているか?

.val()でoptionの選択を変更

trg.val('tokyo-shibuya'); //初期選択値をリセット

これより上の行で変数trgにselect要素のidを代入しています。
このselect要素の選択を.val()で強制的に操作していることになります。
val(val) – jQuery 日本語リファレンス

GoogleMapを切り替える関数を作成

function fadeMap(mapurl , maparea){
$addMap.attr('src' , 'https://www.google.com/maps/embed?pb=' + mapurl ).hide();
$('iframe:first-child' , maparea).remove();
 $addMap.show().attr('frameborder' , '0'); 
 }

addMapはjQueryで作られた空のiframe要素ですが、src=””を指定した状態で非表示にしておきます。

後で出てきますがmapurlは前述の「埋め込みGooglemapの末尾の文字列」です。

対象のエリアにあるiframe要素の一番最初のものが.remove()で消去されて、先ほどの$addMapshow()で出現します。

ここまでの処理を関数呼び出し時に行うのが関数fadeMapです。

$.eachを使って情報を置き換える関数を作成

/////////情報を書き換える関数
 function writeTable(data , areacode){
var table = $(".adress");
 var place = table.find(".place dd")
 var tel = table.find(".tel dd")
$.each(data, function(i ,shopdata){
 //data 配列
 // shopdata 処理中の要素
 var shop = $(this);
place.text(shopdata[areacode].adress); //jsonファイルのadressキーの値
 tel.text(shopdata[areacode].telnum);//jsonファイルのtelnumキーの値
 fadeMap(shopdata[areacode].map);//jsonファイルのmapキーの値
 });
}

最初らへんで、テキストを入れ替える場所を定めて変数に入れておきます。

その下の$.each()から処理が始まるわけなんですが、each()がオブジェクトに対して処理を行うのに対し、
$.eachは今回だとJSONデータの配列に対して連続した処理を行います。

$.each(処理する配列 , function(ループカウンター , 値){~})

第二引数の関数の「値」は、ループ中の「現在処理中の値」を表す変数です。shopdataがそれですね。
で、先ほど掲載したJSONファイルの「”tokyo-shibuya”~”ohsaka”配列」が順にここに入ります。

その下で、先ほど定めた任意の場所へJSONデータの値を入れています。ここではtext()を使って書き換えますが、テキストの内容を取り出すために先ほどのshopdataから値を取り出します。これはJSONデータのとおり、配列でしたね。
「[areacode]」でオブジェクト名を指定して値を引き出していますが、これは関数呼び出し時にわかるので後にします。

ちなみにしれっと前項のfadeMap関数を呼び出しています。これもshopdata[areacode]を使っています。

.on(‘change’)でselect要素の変化を感知する

/////////select要素をchangeしたときにする処理
 trg.on('change' , function(){
maparea = $('div#mapArea');//googleマップを包む親要素
 //セレクトボックス変更した時点で追加
 var maparea.append('<iframe class="addMap" frameborder="0" />');
 var addMap = $('iframe.addMap');
var areacode = $(this).attr('value'); //option value=""でjsonのキーを参照
$.get(shopdataFile , function(data){
 writeTable(data , areacode);
 }).fail(function(){
 $('<p />').appendTo('div.adress').text('店舗データをロードできませんでした。');
 });
});

このtrgはちょっと前に作った変数で、select要素が代入されているものでした。
onでイベントの感知をして処理を発動させます。
.on() | jQuery 1.9 日本語リファレンス | js STUDIO

select要素が変更される度に処理が始まります。

まず変数mapareaにGooglemapを表示させるため、対象となる領域を代入します。
そこに.append()を使ってGooglemap用のiframeをぶち込みます。この時点では何のページも参照していないので、表示されていません。

このGooglemap用iframeを変数に代入して後で使えるようにしておきます。

この変数addMapmapareaはどこで使うかというと、Googlemap切り替え用の関数fadeMapの中です。

その下で変数areacode変数を設定しています。
これは変更後のoption要素のvalue=””値を取得し、代入しています。
これがJSONデータを引っ張ってくる大事な要素となります。

$.getでJSONデータを取得する

$.get(shopdataFile , function(data){
 writeTable(data , areacode);
 }).fail(function(){
 $('<p />').appendTo('div.adress').text('店舗データをロードできませんでした。');
 });

第一引数にJSONファイルのURL、第二引数に関数を書きます。
この関数に渡される変数dataには、第一引数で指定したファイルの中身、つまり処理をするデータが入っています。

そしてここで、さきほど説明した、関数writeTable()を呼び出します。
この関数にdata変数に入っているJSONデータと、選択したoption要素の「value=””値」が代入されているareacode変数を渡します。

選択したoption要素value=””値が、JSONデータの配列を格納しているオブジェクトの名前と一致することで
関数writeTableの「shopdata[areacode].telnum」などの箇所で値が呼び出せることになります。

例えばoptionで
<option value=”tokyo-shinjuku”>東京 新宿ルミネ店</option>
を選択すると、valueの「tokyo-shinjuku」がareacode変数で渡され、
shopdata[“tokyo-shinjuku”].telnumとなり、JSONデータ中の

"tokyo-shinjuku" : {
 "name" : "新宿店" ,
 "adress" : "これは【新宿店】の住所です。" ,
 "telnum" : "03-2222-2222" , //←これ
 }

03-2222-2222が呼び出せます。

$.getでデータが出力出来なかった時の処理.fail()

エラーが出た時の処理を記述することができます。

$.getに続けて、「.fail()」を使いましょう。
この中にfunction(){}と書き、そこに綴った処理が、JSONデータを取得できなかったときに実行されます。

例ではpタグをappendしていますが、これはエラーが出る度に延々とpが追加されてしまうため良くないですね。アラートとか出すほうがいいかと思います。

なんやかんやで、完成です。
以下のサンプルで、選択項目を切り替えてみてください。

JSONを取得して項目を切り替えるデモ

おまけ:.each()でループカウンターを使う

先ほど説明した$.each()の第二引数の関数ではループカウンターを使うことができます。
処理の回数分、0から数値が加算されていくんですね。

実は通常の.each()でもこれが出来るのです。

$('div').each(function(element , i){
$(element).text(i);
});

$.each同様に、elementには、現在処理中の要素が入ります。
$(this)と同じ意味合いですね。

$.get()でなく$.ajax()を使う場合

今回は$.get~.failで実装しましたが、「$.ajax()」を使うと以下のようになります。

$.ajax({
 url: shopdataFile ,
 dataType : 'json' ,
 success :
 function(data){
 writeTable(data, areacode);
 } ,
 error : function(){
 $('<p />').appendTo('div.adress').text('店舗データをロードできませんでした。')
 }
 });

$.ajax() | jQuery 1.9 日本語リファレンス | js STUDIO

dataTypeで「json」を設定し、受信が成功した場合を「success」失敗した場合を「error」に書きます。
こちらの方がコードを見て解りやすいかもしれませんね。

 

以上、JSONデータをJQueryで取得する連携の処理でした!

でわ!

プロフィール

東京でWebデザイナー・コーダーとして、フロントエンド的なことからデザイン思考的なことを考えたりして、ごにょごにょと活動中。(ポートフォリオ)Webクリエイターでは珍しい(?) HIPHOP, R&B好き。休日はよくカフェや漫画喫茶に出向いたりパン屋に行ったりコーヒ豆買いに行ったり、主に散歩しています。。デザインのトレンドやデザイン思考、HTML、CSSからSASS、Javascript、Wordpress構築などコーディングのTIPSなどをブログにアップしていきます。その他のことはtwitter( @satohmsys )まで。コーヒー友達募集中。