JavaScriptのURIのエンコーディングでは、原則
- encodeURIComponent関数
- decodeURIComponent関数
を使用します。
この記事ではその理由と使い方を解説します。
そもそもURIのエンコーディングとは
URIで使用できない文字はエスケープシーケンス(%から始まる代替文字列。エスケープ文字とも言う)に置き換える必要があります。この置き換えをエンコード、元に戻すことをデコードと言います。
例: あ → %E3%81%82 → あ
URIは本来、日本語のようなマルチバイト文字は使えません。ブラウザ上からWebページ等にアクセスする際にはブラウザがデフォルトでエンコードやデコード処理を行ってくれますが、プログラムから直接接続する場合などには自分で処理する必要があります。
JavaScriptのエンコード関数
JavaScriptでURIのエンコード・デコードを行う関数は以下の4つがあります。
原則、URI予約文字列を変換する
- encodeURIComponent関数
- decodeURIComponent関数
を使用してください。
encodeURIComponent関数を使用する理由
実装する処理によっては、URLパラメータ内にURL予約語;,/?:@&=+$-_.!~*'()#が含まれる可能性があります。
この場合、予約語をエンコードしないencodeURI関数ではサーバー側に正しいURL情報を渡すことができません。
URLパラメータに予約文字が含まれる場合、encodeURI関数では正しくURLパラメータを渡せない
http://www.hogemax.com/page?id=001&name=あ&い/うのようなURIの場合、name値としてあ&い/うを取得してほしいのですがあしか取得できません。URLの構文的に予約語である&の前でnameキーが終わってしまうためです。
// http://www.hogemax.com/page?id=001&name=あ&い/う
// 上記URIをencodeURI関数でエンコードしてアクセスした結果↓
const params = new URLSearchParams(window.location.search);
// URLパラメータの値(エスケープシーケンス内に&や/が残っている↓)
console.log(window.location.search); // ?id=001&name=%E3%81%82&%E3%81%84/%E3%81%86
// idパラメータの値
console.log(decodeURI(params.get("id"))); // 001
// nameパラメータの値を取得
console.log(decodeURI(params.get("name"))); // あ
encodeURIComponent関数ならURLパラメータに予約文字が含まれていても正しくURLを渡すことができる
一方、encodeURIComponent関数は予約文字もエンコードするため、あ&い/うから一時的に&や/が消え、一つの文字列としてname値を取得することができます。その後、デコードしてあ&い/うに戻してやればよいわけです。
注意:エンコードが必要な部分ごとにエンコードして結合する設計が必要
前述の通り、encodeURIComponent関数は予約文字も変換します。このため、URI全体を渡すとhttp://などURLを構成する重要な部分まですべてエンコードされてしまいます。
ダメな例
// URLパラメータに&や/を含む場合
const testURLc = "http://www.hogemax.com/page?id=001&name=あ&い/う";
// encodeURIComponentでURI全体をエンコード
console.log(encodeURIComponent(testURLc)); // http%3A%2F%2Fwww.hogemax.com%2Fpage%3Fid%3D001%26name%3D%E3%81%82%26%E3%81%84%2F%E3%81%86
このため、エンコードが必要な部分(URLパラメータの値など)ごとにエンコードして結合するなどの考慮が必要となります。
実装例
上記で示した例ではURLパラメータに予約文字が入ってくる可能性があります。
この場合、URLのテンプレート文字列とURLパラメータ値の変数を用意し、パラメータ値をエンコードしてからURL文字列に埋め込みます。
- パラメータidとnameの値を格納する変数を用意
- idとnameをencodeURIComponent関数でエンコードした結果をURL文字列に埋め込み
let id = "001";
let name = "あ&い/う";
const testURLc = `http://www.hogemax.com/page?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}`;
console.log(testURLc); // http://www.hogemax.com/page?id=001&name=%E3%81%82%26%E3%81%84%2F%E3%81%86
サーバー側でのURLパラメータ取得結果
const params = new URLSearchParams(window.location.search);
// URLパラメータの値
console.log(window.location.search); // ?id=001&name=%E3%81%82%26%E3%81%84%2F%E3%81%86
// idパラメータの値
console.log(decodeURIComponent(params.get("id"))); // 001
// nameパラメータの値を取得
console.log(decodeURIComponent(params.get("name"))); // あ&い/う
name値に&がなくなっているため、%E3%81%82%26%E3%81%84%2F%E3%81%86全体をname値として取得できます。あとはこれをdecodeURIComponent関数に通してあげることであ&い/うを取得できます。
まとめ
今回はJavaScriptでURIエンコーディングを行う際の注意点について解説しました。
予約文字を含まないことが分かっているならencodeURIでも良いかもしれませんが、未来永劫そうとは限りません。基本的にはencodeURIComponentを使用してエンコードを行うようにしましょう。
(というか、encodeURIはどういう時に使うんですかね??)
筆者勉強中の身なので、誤り等ありましたらご指摘いただけますと幸いです。
ブログを書けば勉強できず
勉強すればブログをかけず。
さりとてブログのネタは溜まっていく・・・。
にっちもさっちもいかないですね。