できる気になっているJSを改めてチュートリアルからやってみる 17日目

~~ JSONデータの操作 ~~

最近ちょっとずつまた学びなおす必要が出てきたなぁと思い、いろいろプログラムを勉強しなおしているところなんですが、実はもう今使っている知識は古いのかもと思って、アップデートしようとおもいやってみる会。

実施するのは、この記事

MDN - Javascript

完全な初心者向けと書かれたチュートリアルは全然初心者向けではないって話。アップデートしていきましょう。
JavaScript オブジェクト入門 をやってます。

JSONデータの操作

JavaScript Object Notation(JSON)は表現用の標準的なテキストベースの構造データ表現フォーマット。

JSONは文字列なのでネットワークを通してデータを転送したい場合などに使われます。JSONとJavaScriptオブジェクトを相互に変換できるメソッドを持ったJSONというグローバルオブジェクトがあるので相性よさそう。

{
 "squadName": "Super hero squad",
 "homeTown": "Metro City",
 "formed": 2016,
 "secretBase": "Super tower",
 "active": true,
 "members": [
   {
     "name": "Molecule Man",
     "age": 29,
     "secretIdentity": "Dan Jukes",
     "powers": [
       "Radiation resistance",
       "Turning tiny",
       "Radiation blast"
     ]
   },
   {
     "name": "Madame Uppercut",
     "age": 39,
     "secretIdentity": "Jane Wilson",
     "powers": [
       "Million tonne punch",
       "Damage resistance",
       "Superhuman reflexes"
     ]
   },
   {
     "name": "Eternal Flame",
     "age": 1000000,
     "secretIdentity": "Unknown",
     "powers": [
       "Immortality",
       "Heat Immunity",
       "Inferno",
       "Teleportation",
       "Interdimensional travel"
     ]
   }
 ]
}

という感じ。よく似ています。で、JavaScriptプログラムへ読み込んだ場合(例えば変数 superHeroes へ代入したとき)はオブジェクトのアクセス方法に似ています。

superHeroes.homeTown
superHeroes['active']

さらに深い階層のデータへアクセスする場合は、単純にプロパティ名や配列のインデックスを連結します。

superHeroes['members'][1]['powers'][2]

JSON配列

JSONは配列でも使うことができます。

[
 {
   "name": "Molecule Man",
   "age": 29,
   "secretIdentity": "Dan Jukes",
   "powers": [
     "Radiation resistance",
     "Turning tiny",
     "Radiation blast"
   ]
 },
 {
   "name": "Madame Uppercut",
   "age": 39,
   "secretIdentity": "Jane Wilson",
   "powers": [
     "Million tonne punch",
     "Damage resistance",
     "Superhuman reflexes"
   ]
 }
]

これも有効なJSONです。

注意点

・JSONはデータフォーマットなので、プロパティのみを含むことができメソッドを含むことができません。
・JSONでは文字列とプロパティ名をダブルクォートでくくる必要があります。シングルクォートでくくることはできません。
・一つだけカンマやコロンが抜けているだけで無効なJSONになります。
・JSONは配列やオブジェクトに限らずJSON内に含むことができるデータ型のデータだけでも有効なJSONとなります。ひとつだけの文字列や数値も有効なJSONです。
・プロパティがクォートでくくられていない JavaScriptコードと異なり、JSONではクォートされた文字列だけがプロパティとして使われます。

という事で触ってみましょう

JSONの取得するには XMLHttpRequest(XHR)を使います。これは非常に便利なJavaScriptオブジェクトで、JavaScriptを使用してサーバからリソース(例:画像、テキスト、JSON、さらにはHTMLスニペットなど)を取得するネットワークリクエストを行うことができます。

const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
let request = new XMLHttpRequest();
request.open('GET',requestURL);

という感じで、

・URLを変数へ代入して
・HTTPリクエストを new を使ってリクエストオブジェクトとして作って
・新しいリクエストを開始するには、open() メソッドをつかいます

メソッドは最低2つのパラメータを引数としてとります。今回の例では次の2つの必須パラメータのみを利用します。

・リクエストを開始する際にHTTPのメソッドを決める必要があります。今回のケースでは、単純にデータを取得するだけのGETを使います。
・リクエストを送る先のURL

です。

request.responseType = 'json';
request.send();

は、XHRオブジェクトがサーバから返されるデータを判断できるように responseType にJSONを指定します。するとブラウザ側でJavaScriptオブジェクトへ変換し、そのあと send() メソッドでリクエストを送信します。

request.onload = function(){
   let superHeroes = request.response;
   populateHeader(superHeroes);
   showHeroes(superHeroes);
}

ここでは、先ほどのリクエストに対するレスポンス(response プロパティから取得できます)をsuperHeroesという変数へ代入しています。ここにJavaScriptオブジェクトが格納されます。

では、 populateHeader , showHeroes それぞれの関数を作っていきましょう。

populateHeader 関数を作る

function populateHeader(jsonObj){
   let myH1 = document.createElement('h1');
   myH1.textContent = jsonObj['squadName'];
   header.appendChild(myH1);

   let myPara = document.createElement('p');
   myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed'];
   header.appendChild(myPara);
}

JSONから変換したJavaScriptオブジェクトであるjsonObjを使います。そのjsonの値を使ってごにょごにょしました。

showHeroes 関数を作る

function showHeroes(jsonObj) {
   var heroes = jsonObj['members'];
       
   for (var i = 0; i < heroes.length; i++) {
       var myArticle = document.createElement('article');
       var myH2 = document.createElement('h2');
       var myPara1 = document.createElement('p');
       var myPara2 = document.createElement('p');
       var myPara3 = document.createElement('p');
       var myList = document.createElement('ul');

       myH2.textContent = heroes[i].name;
       myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
       myPara2.textContent = 'Age: ' + heroes[i].age;
       myPara3.textContent = 'Superpowers:';
           
       var superPowers = heroes[i].powers;
       for (var j = 0; j < superPowers.length; j++) {
       var listItem = document.createElement('li');
           listItem.textContent = superPowers[j];
           myList.appendChild(listItem);
       }

       myArticle.appendChild(myH2);
       myArticle.appendChild(myPara1);
       myArticle.appendChild(myPara2);
       myArticle.appendChild(myPara3);
       myArticle.appendChild(myList);

       section.appendChild(myArticle);
   }
}

ごにょごにょ作るこーどです。これで完成。すごいですね。

オブジェクトとテキスト間の変換

XHRリクエストでJSONレスポンスを直接JavaScriptオブジェクトに変換していたので、JavaScriptへのアクセスは単純でした。

しかし、JSON文字列を受け取って、自分でオブジェクトに変換しなければならない場合、またJavaScriptオブジェクトをネットワーク越しに送信したい場合、送信する前にJSON文字列に変換しなければならないです。

そんなとき、ウェブ開発でこの二つの問題にはしょっちゅうでくわすので、ブラウザには組み込みのJSONオブジェクトが備わっていて、これは以下二つのメソッドを備えています。

・parse() : JSON文字列を引数にとり、それに対するJavaScriptオブジェクトを返します。
・stringify() : オブジェクトを引数にとり、等価なJSON文字列形式を返します。

request.open('GET', requestURL);
request.responseType = 'text'; // now we're getting a string!
request.send();

request.onload = function() {
 var superHeroesText = request.response; // get the string from the response
 var superHeroes = JSON.parse(superHeroesText); // convert it to an object
 populateHeader(superHeroes);
 showHeroes(superHeroes);
}

の、JSON.parse(superHeroesText) でJSON文字列をJavaScriptオブジェクトに作り変えます。

んで、stringify() は、全く反対の向きに動作します。

var myJSON = { "name": "Chris", "age": "38" };
myJSON
var myString = JSON.stringify(myJSON);
myString


とが

いいなと思ったら応援しよう!