はじめに
こんにちは!株式会社iimonでフロントエンドエンジニアをしているかとうです!
本記事はiimonアドベントカレンダー13日目の記事となります!✨
サーバーから送信されたデータがShift_JISでエンコードされている場合、そのままだとJavaScriptで扱えないことがありました。
そこで、本記事では以下の内容についてお話しします!
- エンコードについて
- レスポンスがShift_JISレスポンス形式の場合のデコード方法
- JavaScriptエンコード/デコードメソッド
エンコードを理解する
エンコードとは
URLの内容が見やすいので、検索した時のURLをPostmanでリクエストを投げてみます。
クエリパラメータとは
クエリパラメータは、リクエストを行うときにWebサーバーに追加情報を提供します。
URLの?
以降に続く文字列で、KeyとValueのセットで表され、それぞれのパラメータは、&
で結合されます。
Googleの検索クエリに使用した文字列「ねこ」は、キー「q」とペアになっているValueに当たります。
「ねこ」という文字列が「%E3%81%AD%E3%81%93」という半角英数字とパーセント記号の組合せで表されています。
この文字列の変換を、エンコードと言います。今回のURLでのエンコードは、URLエンコードとも言います。
URLエンコードのイメージ
ちなみに、、
Chrome devtoolsのNetWorkでもクエリパラメータを確認することがでいます。エンコードした状態と、デコードした状態のパターンを確認することができます🙆
「view decoded」をクリックした時
「view URL-encoded」をクリックした時
文字コード
文字コードとは、文字や記号などをコンピュータに理解させるために、番号を割り当てた符号のことです。
⭐️ 文字コードで割り当てられた番号のことを、コードポイントといいます!
文字コード規格
ASCII
英数字や一部の記号を表現するための文字コード規格で、0から127までのコードポイントを持っています。例えば、「A」という文字には65のコードポイントが割り当てられています。
Unicode
世界の様々な言語、記号に番号を割り振って定義した文字コードの標準規格です。割り当てられた番号のことをコードポイントといいます。例えば、 「A」という文字には、16進数でU+0041のコードポイントが割り当てられています。
エンコーディング形式
Unicode(UTF-8/UTF-16)
Shift_JIS
主に日本語に使用されるエンコーディング形式で、文字コードは漢字・ひらがな・カタカナ・英数字・一部の記号のコードポイントを持っています。
文字化けの原因
文字列をバイト列としてどのように符号化するか定義されています。エンコーディング形式が異なると、同じコードポイントが異なるバイト列にエンコーディングされ、文字化けしてしまいます。
例えば、UTF-8でエンコードしたものをでShift_JISデコードすると、文字化けが起こることがあります。例えば、日本語の文字が含まれている場合などです。
UTF-8でエンコードして、Shift_JISでデコードするイメージ
Shift_JISのレスポンスを扱う
困ったこと
取得したShift_JISエンコーディング形式のレスポンスを、以下の方法でテキストデータとして取得した時、文字化けしました、、🥵
const html = response.text()
文字化けの原因は、textメソッドはレスポンスを常にUTF-8としてデコードするからです。
❗️ Shift-JISを考慮してデコードする必要があります。
解決した方法
ArrayBuffer()メソッドを使用して、サーバーからのレスポンスをバイナリデータとして取得します。
const arrayBuffer = await response.arrayBuffer();
TextDecoderを使用して、ArrayBufferをShift-JISエンコーディング形式でデコードし、文字列として取得します。
これにより、正しい文字エンコーディングでデータを解釈し、文字化けを防ぐことができます。
const textDecoder = new TextDecoder('shift-jis'); const html = textDecoder.decode(arrayBuffer);
取得したHTML文字列をDOMオブジェクトに変換します。これでquerySelectorメソッドなどを使用しての処理が可能になります。
const parser = new DOMParser(); const doc = parser.parseFromString(str, 'text/html'); const result = doc.querySelector('.selector').textContent;
全体の処理
const textDecoder = new TextDecoder('shift-jis'); const arrayBuffer = await response.arrayBuffer(); const html = textDecoder.decode(arrayBuffer); const parser = new DOMParser(); const doc = parser.parseFromString(str, 'text/html'); const result = doc.querySelector('.selector').textContent;
JSのエンコードメソッド
JavaScriptでのエンコードメソッドについて、簡単にまとめました❕
encodeURI()
以下の文字列は置き換えられません。(予約文字)
A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #
decodeURI()
エンコードされた完全なURIをエンコードされていない状態にします。
const uri = "https://example.com/?x=ねこ"; const encoded = encodeURI(uri); console.log(encoded); // エンコード結果 console.log(decodeURI(encoded)); // デコード結果
出力
https://example.com/?x=%E3%81%AD%E3%81%93 https://example.com/?x=ねこ
encodeURIComponent()
URIを構成する一部の文字列をUTF-8エンコーディングされた文字列に置き換えます。
以下の文字は置き換えられません。(予約文字)
A-Z a-z 0-9 - _ . ! ~ * ' ( )
console.log(encodeURIComponent('cat?')); // "cat%3F" console.log(encodeURIComponent('ねこ?')); // "%E3%81%AD%E3%81%93%EF%BC%9F"
encodeURI()との違い
- 予約文字の種類
- 対象の文字列(完全なURLかURLを構成する一部の文字列)
const uri = "https://example.com/?x=ねこ"; console.log(encodeURI(uri)); console.log(encodeURIComponent(uri));
出力
https://example.com/?x=%E3%81%AD%E3%81%93 https%3A%2F%2Fexample.com%2F%3Fx%3D%E3%81%AD%E3%81%93
decodeURIComponent()
エンコードされたURIを構成する一部の文字をエンコーディングされていない状態にします。
console.log(decodeURIComponent('cat%3F')); // "cat?" console.log(decodeURIComponent('%E3%81%AD%E3%81%93%EF%BC%9F')); // "ねこ?"
decodeURI()との違い
- 予約文字の種類
- 対象の文字列(完全なURLかURLを構成する一部の文字列)
⭐️ encodeURIComponent()
decodeURIComponent()
は、URLのクエリパラメータに使用される検索キーワードなどのエンコードとデコードに対して使用するのがよさそうです。
最後に
ここまで読んでくださり、ありがとうございます!🎄
現在弊社ではエンジニアを募集しています!
この記事を読んで少しでも興味を持ってくださった方は、ぜひカジュアル面談でお話ししましょう!
iimon採用サイト / Wantedly / Green
明日のアドベントカレンダーの記事はkimuraさんです!楽しみです!✨✨