Pocket

こんにちは。ishibashiです。

先日、PHPで json_encode を使った smarty の plugin を作成する機会がありました。
そのときにマルチバイトの扱いで少しハマったので、内容を備忘録として記します。

参考)smartyとは?

下記のようなコードで配列を組み立てた後、json_encodeすることにしました。

<?php
    $title = 'タイトル'
    $json = array('title' => $title,
                  'body'  => 'test');
    echo json_encode($json);
?>

としたところ、期待していた結果は、

{"title":"タイトル","body":"test"}

だったんですが、

{"title":null,"body":"test"}

という結果になってしまいました。

これは、phpのコードがeuc-jpで記述されていたことが原因で、
PHPマニュアルを確認すると、「すべての文字列データは、UTF-8 エンコードされたいなければいけません。」とありました。

そこで下記のように修正しました。

<?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);
?>

そうすると今度は

{"title":"\u30BF\u30A4\u30C8\u30EB","body":"test"}

という結果になってしまいました。

どうやらマルチバイトをエスケープしないようにするには第二引数に JSON_UNESCAPED_UNICODE を指定する必要があるようです。

※このオプションはPHP5.4から追加されています。
PHP5.4以前のバージョンではhex2binなどを使いもう一手間かける必要があります。

<?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);
?>

とすることで、やっと期待していた通りの結果が得られました。

同じような事象に遭遇している方などの参考になれば幸いです。