技術Tips

PHPでjson_encodeしたデータをJSON.parseしたらエラーがでた件

PHPで作成した配列データをフロントのJavaScriptに渡したいとき、PHPの配列をそのまま渡すことはできないのでJSON形式のデータに変換します。

PHPで配列をJSON形式のデータに変換するときはjson_encodeを使いますが、エンコード後のJSONをJavaScriptのJSON.parse()に食わせるとシンタックスエラーになるケースがありました。

ひとまず解決したので備忘録。

JSON.parseで発生した問題

まず、発生した問題について説明します。解決法のみ知りたい方は飛ばしてください。

背景
  • PHPでDBから取得したデータの連想配列をフロントのJavaScriptに渡したかった
  • 連想配列をそのまま渡せないのでJSONの形にする必要がある
  • JavaScriptでは受け取ったJSONをオブジェクトに展開して使いたい

PHPで配列データをJSON形式に変換するにはjson_encodeを使います。

// PHP
$dataArray = array('id' => '1', 'name' => 'taro');
$jsonString = json_encode($dataArray);

JavaScriptでJSON文字列をオブジェクトに展開するのはJSON.parseです。

// JavaScript
const obj = JSON.parse('<?php echo $jsonString ?>');
// JSON.parseすることでobjのプロパティにデータが展開される

この実装でよしとしていたんですが、当該ページが動かないと報告を受け、実際にその時のデータで再試すると確かに動かない。

ブラウザのデバッガで確認すると、JSON.parseしている行でJavaScriptのシンタックスエラーが発生していました。

原因は特殊文字

JSON.parseでエラーが発生した原因は、JSON文字列内に特殊文字が入っていたためでした。

JSONを扱うときにはJSON文字列として正しい形かの他に、特殊文字がHTMLやJavaScriptの構文解釈に影響を与えないか注意しなくちゃいけない。

// PHP
$dataArray = array();
$dataArray += array('id' => '1', 'name' => 'ta"'"ro');
$dataArray += array('id' => '2', 'name' => 'ta"ro');
$jsonString = json_encode($dataArray);

上のコードはちょっと無理やりですが、$dataArrayのnameの中に’(シングルクォーテーション)や”(ダブルクォーテーション)が入っていて、JSON.parseするとエラーになります。

「’」や「”」はJSONで特別な意味がある特殊文字なので適切なエスケープが必要です。

JSONの特殊文字をエスケープする

PHPのjson_encodeで特殊文字をエスケープするには、以下のようにオプションを指定します。

// PHP
$jsonString = json_encode($dataArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);

JSON_HEX_TAG
<を¥u003C、>を¥u003Eに変換するオプション。

JSON_HEX_AMP
&を¥u0026に変換するオプション。

JSON_HEX_APOS
‘を¥u0027に変換するオプション。

JSON_HEX_QUOT
“を¥u0022に変換するオプション。

これらのオプションを指定してjson_encodeすれば一部を除いてJSON.parseのエラーは解消するはず。

なぜ一部なのかというと、今回僕が遭遇したケースでは解消しなかったためです。
その原因と解決策を以下説明します。

特殊文字をエスケープしてもJavaScriptでエラーになる場合

僕が遭遇したケースでは”(ダブルクォーテーション)をJSON_HEX_QUOTオプションで¥u0022に変換してもJSON.parseのシンタックスエラーは消えませんでした。

多分JavaScriptとして解釈しようとすると、文中に急に「”」が出てきたから、そこまでが文字列として認識されてしまっている。これについても問題ないようエスケープする必要があります。

それを踏まえてPHP(JSON生成側)の最終形コードは以下の形となりました。

// PHP
$jsonString = json_encode($dataArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
$jsonString = str_replace('¥u0022', '¥¥¥"', $jsonString);

「”」を「¥”」でエスケープしています。

JSON_HEX_QUOTが冗長なので直接「”」を置き換えたほうがいいかも。

Webプログラミングの第一歩

プログラミング学習の第一歩に最適なのは、動くものを作ってみることです。

しかしプログラミング未経験の方がテキストを読みながら動くものを作るのは非常に敷居が高いです。

Udemyの講座なら実際に講師の方が動画で説明してくれるため、イメージが掴みやすくとっつきやすいです。

おすすめの講座を知りたい方はこちらの記事をご覧ください。

おすすめUdemy講座7選を見てみる

RELATED POST