こんにちは。ishiBです。
先日、PHPで json_encode を使った smarty の plugin を作成する機会がありました。
そのときにマルチバイトの扱いで少しハマったので、内容を備忘録として記します。
参考)smartyとは?
下記のようなコードで配列を組み立てた後、json_encodeすることにしました。
[sourcecode language="php"] <?php $title = 'タイトル' $json = array('title' => $title, 'body' => 'test'); echo json_encode($json); ?> [/sourcecode]
としたところ、期待していた結果は、
[sourcecode language="php"] {"title":"タイトル","body":"test"} [/sourcecode]
だったんですが、
[sourcecode language="php"] {"title":null,"body":"test"} [/sourcecode]
という結果になってしまいました。
これは、phpのコードがeuc-jpで記述されていたことが原因で、
PHPマニュアルを確認すると、「すべての文字列データは、UTF-8 エンコードされたいなければいけません。」とありました。
そこで下記のように修正しました。
[sourcecode language="php"] <?php $title = 'タイトル' $json = array('title' => mb_convert_encoding($title, "UTF-8", "EUC-JP"), 'body' => 'test'); $json = mb_convert_encoding($json, "EUC-JP", "UTF-8") json_encode($json); ?> [/sourcecode]
そうすると今度は
[sourcecode language="php"] {"title":"\u30BF\u30A4\u30C8\u30EB","body":"test"} [/sourcecode]
という結果になってしまいました。
どうやらマルチバイトをエスケープしないようにするには第二引数に JSON_UNESCAPED_UNICODE を指定する必要があるようです。
※このオプションはPHP5.4から追加されています。
PHP5.4以前のバージョンではhex2binなどを使いもう一手間かける必要があります。
[sourcecode language="php"] <?php $title = 'タイトル' $json = array('title' =--> mb_convert_encoding($title, "UTF-8", "EUC-JP"), 'body' => 'test'); $json = mb_convert_encoding($json, "EUC-JP", "UTF-8") json_encode($json); ?> [/sourcecode]
とすることで、やっと期待していた通りの結果が得られました。
同じような事象に遭遇している方などの参考になれば幸いです。