PHPに限らず、文字コードとエスケープの問題は度々発生します。
今回主に取り扱うものは、PHPでのURLエンコードに絡むものです。
実際のところ、嵌まりやすいのは文字コードの方ですね。
分かれば簡単でも最初は意外と時間がかかるものなので、しっかり確認しておきましょう。
こんな方におすすめ
- API開発を予定している
- URLやパス情報を含むjsonデータを使っている
- APIと実際のデータに違いがあり困っている
スラッシュ「/」のエスケープはjson_encodeのオプションで解決可能!まずはリファレンスの確認をしよう!
結論としては、スラッシュのエスケープはjson_encodeのオプション(JSON_UNESCAPED_SLASHES )で解決できます。
ただし、デフォルトでは無効になっているため明示が必要です。
JSON形式とは?PHPにおけるjson_encodeの動作について
まずは、JSON形式とjson_encodeと動作について確認しておきます。
JSON(JavaScript Object Notation)は名前の通り、javascriptのデータ構造がベースです。
json_encodeとは、PHPの配列やオブジェクトなどからjson形式を生成する関数です。
PHPのデータがJSON構造ではないので、json_encodeは文字列に変換されます。
文字列状態では加工が難しく、データをいじる場合は変換前が原則です。
json_encodeの公式リファレンス: https://www.php.net/manual/ja/function.json-encode.php
json_encodeのデフォルト動作とは?
上記URLのリファレンスで確認できますが、初期ではオプション(flags)が0になっています。
つまり、オプションで指定しない限りそれらは行われません。
json_encodeで指定できるオプションは、こちらから確認できます。
オプションページを見ていただければ確認できますが、「flag: 0」は何もしないわけではありません。
例えば「JSON_UNESCAPED_UNICODE 」というフラグを指定すると、全角Unicodeのエスケープをしないように設定できます。
JSON_UNESCAPED_UNICODE (int)
マルチバイト Unicode 文字をそのままの形式で扱います (デフォルトでは \uXXXX にエスケープします)。
べき論に近い形で設定されているものもあるため、事前の確認をおすすめします。
本題!URLの非エスケープ「JSON_UNESCAPED_SLASHES」の使い方
では、実際にURLの非エスケープ化について見ていきます。
エスケープあり/なしでどのような結果になるのか、結果は以下の通りです。
【URLエスケープあり】
$noEsc = json_encode(["url" => "https://example.com"]);
var_dump($noEsc);
出力: string(31) "{"url":"https:\/\/example.com"}"
【URLエスケープなし】
$esc = json_encode(["url" => "https://example.com"], JSON_UNESCAPED_SLASHES);
var_dump($esc);
出力: string(29) "{"url":"https://example.com"}"
実行結果の通り、フラグを付けることで「/」の前に「\」が付かなくなりました!
フラグさえ知っていれば、なんとこともありません。
逆に、正規表現などで解決しようと思うと大分面倒です。
車輪の再発明は、避けたいところですね。
json_encodeの「/」エンコード問題はフラグで一発解決が可能。オプションを便利に使いこなそう!
今回取り上げたjson_encodeのように、関数やフラグなどで解決できる問題は数多くあります。
優先で探すべきは、原則としては以下のような順番がおすすめです。
- 言語の標準仕様
- 言語の標準、拡張関数
- 外部ライブラリ
- 自己解決
開発済みのものはパフォーマンスなども最適化されている可能性があり、使わない手はありません。
jsonは広く使われるデータ構造なので、この際にオプションを一読してみてはいかがでしょうか。