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が冗長なので直接「”」を置き換えたほうがいいかも。

この記事が気に入ったら
フォローしてね!

よかったらシェアお願いします!
URLをコピーする
URLをコピーしました!
タップできる目次
閉じる