どんな時にJSONが必要?
さて、まずはJSONの構造とかJSONファイルをJavaScriptで扱う方法とかを紹介する前に、そもそも『どんな時にJSONファイルが必要となるのか?』…という点を明確にしておきましょう。
冒頭で述べたように、ただシンプルなWebサイトを作成するだけであればJSONを扱う必要は全くありません。
では、どのような場合にJSONを扱う必要性が出てくるのでしょうか?
その多くは、API連携を行う場合…言い換えれば、どこか(何か)と通信を行う場合です。
なので、ただWebページを表示させるだけで良い場合は必要ない=JSONを扱わずにWebページを作成することは可能…というわけですね。
例えば、コーポレートサイトを作るとして、会社やスタッフの写真と企業理念、会社概要などしか掲載しない場合は、API連携(JSONファイルとの通信)は必要ありません。
ですが、お問い合わせフォームを設置するとなった際に、冒頭で例に出したように『郵便番号を入力してボタンをクリックすると、住所が自動で入力される仕組み』を実装する必要が出たとしましょう。
この機能を実装するには、全国の郵便番号と住所のデータが必要になりますよね。
もちろん、自分で地道に調べてデータベースを作成し、一から自動入力の仕組みを作り上げることも不可能ではありません。
しかし、ものすごく手間がかかりますし、現実的とは言えません。(少なくとも筆者はそんな手間暇かけたくありません)
そこでよく使われているのがAPI連携という仕組みであり、その時に出てくるのがJSONです。
後述しますがJSONはJavaScriptのオブジェクトの形式になっているので、プログラミング言語側にも人間側にも読みやすく、サイズも軽量なので通信を行うファイル形式としてはまさに打って付けというわけです。
ということで、JSONが何なのかよくわからんという方は、JSON = 外部の何らかのサービスを利用する際によく使われている通信に適した構造のファイル形式 …というイメージを持っておくと良いと思います。
POINT!
- ・ただ静的なWebページを表示させるだけならJSONは必要ない!
- ・外部サービス(API連携)を利用する場合に、通信フォーマットとしてJSONが使われる(ことが多い)!
- ・例として、郵便番号から住所を自動入力できるようにしたい場合などが挙げられる!
JSONの構造
JSONの構造はJavaScriptのオブジェクトとほぼ同様で、keyとvalueの関係から成り立ちますが、JavaScriptオブジェクトとはいくつか違いがあります。
まず、keyは"
(ダブルクォーテーション)で囲む必要があります。
数値をkeyにしたいからと言って、下のようにするとJSONファイルとして機能しなくなるので注意しましょう。
// 間違っている例
{
1: "value"
}
なお、上の例では分かりやすくするためコメントを掲載していますが、JSONではJavaScriptファイルのような形でコメントを残すことはできないので、この点にも注意が必要です。
通常、keyを単純な数値にすることはあまりないと思いますが、数字にするにしても次のようにする必要があります。
Valueの方は、文字列でない数値や真偽値は"
(ダブルクォーテーション)で囲む必要はありません。
{
"boolean": true,
"number": 100
}
また、複数のkey-valueを設定する場合は【,
(カンマ)】で区切る必要がありますが、最後のkey-valueには【,
(カンマ)】をつけてはいけません。
こたとえば、下の例はJSONファイルとして不正ということになります。
{
"boolean": true,
"number": 100, // 最後のkey-valueにカンマがついているのでNG
}
JavaScriptのオブジェクトでは、下のように最後のkey-valueにカンマがついていてもエラーになりません。
ですが混乱を招くので、どちらの場合でも最後のkey-valueにはカンマをつけないというルールを定めておくと良いかもしれません。
const orangeObject = {
name: "orange",
price: 100, // これはエラーにはなりません
}
また、JSONは下のように階層構造にすることも可能です。というか、このような形式の方をよく目にするかと思います。
{
"colorSetting": {
"color": "red",
"backgroundColor": "lightpink"
},
"fontSetting": {
"fontSize": "16px",
"fontFamily": "sans-serif"
}
}
いくつか重要な違いがあるとは言え、見た目はほとんどJavaScriptのオブジェクトと同じですね。
プログラム側(JavaScript)にとっても解析しやすいデータ形式と言えますし、我々人間から見てもその構造を理解しやすいので、データ通信を行う際のスタンダードとして広く浸透したのだと考えられます。
なお、データ通信はXML形式など他のファイル形式でも行えますが、JSONで扱えるデータの範囲内であればJSONの方がメリットが大きいと言えるでしょう。
前章では、JSONが用いられる例として住所の自動入力を挙げましたが、住所データを公開しているAPIと連携を行うことで、必要な住所のデータがJSON形式のファイルで得られる(通信できる)ということになります。
POINT!
- ・JSONの構造は、JavaScriptオブジェクトとほぼ同じ!
- ・ただし、keyは
"
(ダブルクォーテーション)で囲む必要があり、数値などをそのままの形では利用できない!
- ・コメントを残せない点や、,(カンマ)の有無などにも注意が必要!
JSONファイルの通信テストに必要な環境
冒頭でも触れましたが、JavaScriptを本やWebで学んだのに、JSONやそれに伴うFetch APIの知識はなぜかあまり身につかなかった…というケースは、きっと珍しくないことだと思います。
それは、既に述べたように、『API連携を行ったりしない限りJSONを扱う必要がないから』…という要因もあるのですが、もう一つ大きな要因があります。
その要因とは、『JSONファイルとの通信はローカル環境ではテストしづらく、本やWebの記事を読んで理解するだけに留まってしまいがちだから』…というものです。
本題からズレるので詳しくは説明しませんが、CORS(Cross-Origin Resource Sharing)というブラウザのセキュリティシステムにより、ローカルに保存したJSONファイルをローカルのHTMLファイルから読み込もうとするとエラーになります。
なので、JSONファイルとの通信に関しては、『ローカル環境でちょろっとコードを書いてテストする』ということが難しいんですね。
これを解決する手段は主に4つあります。
1つは、ブラウザのセキュリティ機能を一時的にオフにするという方法です。
しかし、この方法は経験豊富な開発者でない限り避けた方が良いと思います。
CORSはそもそも、悪意のあるスクリプトなどからユーザーを守ってくれるための大事なセキュリティ機能です。
万が一、設定をミスったり、変更した設定を元に戻すのを忘れたりしてしまったら、甚大な被害が及ぶ可能性もなくはありません。
少なくとも、JavaScriptを学び始めたばかりの初心者が選択する方法としては悪手だと言えるかと思います。
そして解決策2つ目は、実際のAPIサービスを使ってテストするという方法です。
実際に広く公開されているAPIサービスをテスト目的で利用する分には、ほとんど問題やリスクは無いと考えて良いかと思います。
ただし、APIにはそれぞれ利用規約があるのでなんでも好き勝手にできるわけではないですし、返されるJSONデータが複雑かつ多量である場合が多いので、初心者がテストとして利用するにはやや扱いづらいです。
また、APIを利用するには提供元サービスに開発者登録をしなければならない場合も多く、そういった面でも少しハードルが高いかもしれません。
なので、この2つ目の方法も、筆者としてはそこまでオススメできるものではありません。
筆者的にオススメなのは、これから紹介する3つ目と4つ目の方法です。
解決策3つ目は、『ローカルサーバーを構築する』という方法です。
Node.jsのhttp-serverなどを利用すると、ローカル環境に仮想的なサーバーを設置することができます。
ローカルサーバーを利用することで、リソースはfile://~ではなく、http://localhost:<ポート番号>/という形でアクセスされるようになります。
詳しい説明は省きますが、要するにCORSのセキュリティ問題をクリアできるということです。
VSCodeをお使いの方は、Live Previewなどローカルサーバー機能が含まれているプラグインを利用することで、とても簡単にローカルに保存したJSONファイルと通信を行い、テストを行うことができます。
お手軽かつ無料でテストができるという一石二鳥な方法なので、まずはこの方法でJSONファイルのテストを行い、JSONやFetch APIの基本を学ぶと良いと思います。
そしてもう一つ、筆者がオススメするのは、4つ目の『レンタルサーバーを借りて、そこで思う存分にテストを行う』という方法です。
Web関連のスキルを身につけるためにJavaScriptを学んでいるのであれば、どうしても『本番環境でも試したい』と思う場面が多々出てきます。
そうなると結局、レンタルサーバーを借りてしまうのが一番手っ取り早いです。
借りている間はランニングコストがかかりますが、必要がなくなれば解約すれば良いわけですし、そもそも少容量・小規模のレンタルサーバーであれば費用はそんなにかかりません。(スマホの料金の方がよっぽど…笑)
レンタルサーバーを借りることで本番環境のテストが簡単に行えるようになるだけでなく、サーバー周りの基本的な知識も自然と身につけられます。
なので、最初はローカル環境で学ぶにしても、最終的にはレンタルサーバーを借りて、本番に限りなく近い環境で色々と自由にテストをしてみるのがオススメです。(利用規約の範囲内で)
レンタルサーバーの同一ドメインにHTMLファイルとJSONファイルをアップロードすれば、CORSのセキュリティ問題は解決できます。
次の章では、3つ目の『ローカルサーバーを構築する』方法(VSCode + プラグイン)を用いて、実際にJSONファイルと通信をテストしてみたいと思います。
POINT!
- ・JSONファイルを使った通信は、ローカル環境ではテストしづらい!
- ・初心者がブラウザのセキュリティ設定を下手にいじくるのはリスクあり!
- ・オススメはローカルサーバーを構築して安全にテストする方法!
ローカルサーバー上で通信をテストする
それではVSCodeとLivePreviewプラグインを使って、JSONファイルを利用した通信のテストをしてみましょう。
まずはVSCodeを立ち上げて、JSONファイルを作成します。
Ctrl(⌘)+Nを押して新しいファイルを作成し、ファイル形式の選択でJSONを選びます。
今回は、郵便番号を入力すると住所が自動表示される機能の超簡易版を作ってみたいと思います。
簡単なテストを行うだけなので、郵便番号と住所を紐付けたデータの数は2つぐらいにしておきます。
{
"data1": {
"zipCode": 1050004,
"address": "東京都港区新橋"
},
"data2": {
"zipCode": 1350053,
"address": "東京都江東区辰巳"
}
}
出来上がったJSONファイルは、zip_address_data.jsonというファイル名で保存しておくこととします。
そして、HTMLで郵便番号入力欄と住所入力欄、そして郵便番号から住所情報を自動入力するボタンを設置しておきます。
なお、実際のフォームではないのでformタグは使っておらず、マークアップはわりとテキトーです。
<div class="container">
<div>
<input type="number" id="zipcode_input" placeholder="(例)1050004">
<button id="zipcode_to_address_btn">郵便番号から住所を入力</button>
</div>
<input type="text" id="address_input" size="50" placeholder="住所を入力">
</div>
入力フォームが見やすくなるようにCSS調整も行なっておく必要がありますが、そこは本題ではないので省略します。
さて、事前準備ができたらいよいよJavaScriptの出番です。
まずは必要な要素情報の取得と、郵便番号・住所情報を格納しておくための変数を宣言しておきます。
const zipcodeInput = document.getElementById("zipcode_input");
const addressInput = document.getElementById("address_input");
const zipcodeToAddressBtn = document.getElementById("zipcode_to_address_btn");
let userZipCode;
let userAddress = "";
そして次に、郵便番号を入力するとその番号情報を数値(Number)として変数userZipCodeに格納されるようにします。
zipcodeInput.addEventListener("input", (e) => {
userZipCode = Number(e.currentTarget.value);
});
ユーザーが郵便番号を入力し終えて、『郵便番号から住所を入力』ボタンが押されたら、指定のJSONファイルとの通信を試みます。
なお、通信処理は時間がかかる場合があるため、非同期処理と呼ばれる方法で実行します。
非同期処理に関してはかなり奥が深く、それだけで記事が何個も書けてしまうぐらいです。
なので、プログラミング初心者のうちはあまり深追いせず、『そういうのもあるのね』程度に留めておいた方が良いかもしれません。
ここでは、非同期処理=『処理が終わるまで他の処理を全て止めて待ち続けるのではなく、通信処理を行なっている間に他の操作や処理も行えるようにする』…ぐらいの認識で大丈夫です。
JSON、async/await、then…このあたりのキーワードが出てきたら、『これは非同期通信に関係するものだ』と思えばOKです。
なお、JSONファイルはJavaScriptのオブジェクト構造に似てはいるものの、全く同じでははないので、そのままでは利用しづらいです。
なので、通信を試みた結果、通信が成功してJSONデータが返されたらデータを次のように加工処理を行う必要があります。
- ・JSON→JavaScript Object
- Response.json()メソッドで、JSONからJavaScriptオブジェクトを生成
- ・複数のJavaScriptオブジェクト→配列
- Object.entries()メソッドで複数のJavaScriptオブジェクトを配列の構造に変換
こうすることで、JSONデータを扱いやすいJavaSciptオブジェクトの配列として扱うことができるようになります。
通常の配列と同じく、目的のデータをfind()メソッドで配列のデータ内に一致するものを探すことも簡単にできます。
以上を踏まえて、JSONと通信を行う部分のコードを見てみましょう。
zipcodeToAddressBtn.addEventListener("click", async() => {
try {
const res = await fetch('zip_address_data.json');
const json = await res.json();
const data = Object.entries(json);
const matchZipcode = data.find( (data) => {
return data[1].zipCode === userZipCode;
});
if(matchZipcode !== undefined) {
userAddress = matchZipcode[1].address;
addressInput.value = userAddress;
} else {
console.error("該当する住所が見つかりません");
}
} catch {
console.error("通信に失敗しました");
}
});
fetch()は、JSONファイルとの通信を試みた結果をPromiseとして返します。
なので、例えばローカルサーバーを構築するのを忘れていた場合や、ファイルパスを間違えていた場合などは通信に失敗するので、その失敗結果が返され、catchブロックの処理である『通信に失敗しました』のエラーログが表示されることになります。
ただし、上の例ではコードの構造をシンプルする目的でtryブロックの範囲を広げているため、通信エラーの他にJSONパースエラーやデータ構造の問題もキャッチされる可能性があります。
なので、本番ではもう少し細かくエラーを捕捉できるよう改良を加えると良いでしょう。
通信が成功したら、JSONをJavaScriptオブジェクトとして解析し(await res.json())、さらにその解析成功結果を利用して、JavaScriptオブジェクトを配列構造にしています。(Object.entries(json))
その後、if文とfind()メソッドを使ってユーザーが入力した郵便番号にマッチするものがあるかどうかを判定し、マッチするものがあれば住所情報(userAddress)を住所入力欄として配置しているinput要素のvalueとして指定します。
ここで、data[1]となっているのは、元々のJSONが"
data1"
: { "
zipCode"
: ~ }…という構造であるため、data[0]には"
data1"
といった文字列が格納され、zipCodeなどのデータはdata[1]の方に格納されることになるからです。
このサンプルを実際にテストした様子が下の動画です。
以上、JSONを使った簡易的な通信処理テストの紹介でした!
ちなみにですが、JavaScriptだけで外部ファイル(JSON)と通信ができるからと言っても、そのままの設定でクライアントサイドからJSONファイルを自由に書き換え(更新)ができるというわけではありません。
サーバーサイドでAPIの設定を行えば、JavaScriptを使ってクライアントサイド(Webブラウザ上)からサーバに置かれたJSONファイルを更新することも不可能ではないですが、基本的には読み取り専用として利用するものだと考えてOKです。
JSONは技術的に書き換え不可というものでは決してないですが、ユーザーが自由に書き換えたりできるような状況で提供される・利用するといったシーンは、普通はあまりない…という認識を持っておくと、より正確です。
JSONはデータベースのようにトランザクション管理やバックアップ機能に優れているわけではないので、JavaScriptで通信処理もできるからと言っても、サーバーサイドの知識やスキルが不要になるわけではありません。
JSONとそれを利用した非同期通信は色々なところで利用されていますし、とても便利なものではありますが、JSONだけでなんでも完結できるほど万能なものでもない…というイメージを持っておくと良いかと思います。
POINT!
- ・fetch()で通信を試みることができる(Promiseが返される)!
- ・JSONはそのままではデータを利用しづらいので、解析・整形する必要がある!
- ・JSONは便利なものだが、なんでもできると言えるほど万能なものではない!