LoginSignup
20
26

More than 5 years have passed since last update.

json_encode における JSON_UNESCAPED_UNICODE に PHP5.3 で対応する

Last updated at Posted at 2016-02-13

はじめに

こちらの記事で題目について議論していたのですが,コメントが長く続いてしまって読みにくいので要点だけまとめておきます. @sounisi5011 さんご指摘ありがとうございました.

実装

個人的に一番スッキリしていると感じるものを載せておきます.

function raw_json_encode($input, $flags = 0) {
    $fails = implode('|', array_filter(array(
        '\\\\',
        $flags & JSON_HEX_TAG ? 'u003[CE]' : '',
        $flags & JSON_HEX_AMP ? 'u0026' : '',
        $flags & JSON_HEX_APOS ? 'u0027' : '',
        $flags & JSON_HEX_QUOT ? 'u0022' : '',
    )));
    $pattern = "/\\\\(?:(?:$fails)(*SKIP)(*FAIL)|u([0-9a-fA-F]{4}))/";
    $callback = function ($m) {
        return html_entity_decode("&#x$m[1];", ENT_QUOTES, 'UTF-8');
    };
    return preg_replace_callback($pattern, $callback, json_encode($input, $flags));
}
  • \uXXXX にマッチする文字列を &#xXXXX; 形式に変換し,html_entity_decode で復元します.
  • \\\uよりも優先的に無視します.
  • JSON_HEX_TAGが指定されたとき,\u003C:< または\u003E:>を無視します.
  • JSON_HEX_AMPが指定されたとき,\u0026:& を無視します.
  • JSON_HEX_APOSが指定されたとき,\u0027:' を無視します.
  • JSON_HEX_QUOTが指定されたとき,\u0022:" を無視します.

動作確認

PHP 7.0
<?php

function raw_json_encode($input, $flags = 0) {
    $fails = implode('|', array_filter(array(
        '\\\\',
        $flags & JSON_HEX_TAG ? 'u003[CE]' : '',
        $flags & JSON_HEX_AMP ? 'u0026' : '',
        $flags & JSON_HEX_APOS ? 'u0027' : '',
        $flags & JSON_HEX_QUOT ? 'u0022' : '',
    )));
    $pattern = "/\\\\(?:(?:$fails)(*SKIP)(*FAIL)|u([0-9a-fA-F]{4}))/";
    $callback = function ($m) {
        return html_entity_decode("&#x$m[1];", ENT_QUOTES, 'UTF-8');
    };
    return preg_replace_callback($pattern, $callback, json_encode($input, $flags));
}

$data = ['あ\い\\u26A0う\\\\u26A0え\\u26A0お', '<x>& \' "</x>'];
$options = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT;

echo 'json_encode:                 ', json_encode($data, JSON_UNESCAPED_UNICODE), "\n";
echo 'raw_json_encode:             ', raw_json_encode($data), "\n";

echo "\n---\n\n";

echo 'json_encode:                 ', json_encode($data, JSON_UNESCAPED_UNICODE | $options), "\n";
echo 'raw_json_encode:             ', raw_json_encode($data, $options), "\n";
echo 'raw_json_encode (redundant): ', raw_json_encode($data, JSON_UNESCAPED_UNICODE | $options), "\n";

/*

json_encode:                 ["あ\\い\\u26A0う\\\\u26A0え\\u26A0お","<x>& ' \"<\/x>"]
raw_json_encode:             ["あ\\い\\u26A0う\\\\u26A0え\\u26A0お","<x>& ' \"<\/x>"]

---

json_encode:                 ["あ\\い\\u26A0う\\\\u26A0え\\u26A0お","\u003Cx\u003E\u0026 \u0027 \u0022\u003C\/x\u003E"]
raw_json_encode:             ["あ\\い\\u26A0う\\\\u26A0え\\u26A0お","\u003Cx\u003E\u0026 \u0027 \u0022\u003C\/x\u003E"]
raw_json_encode (redundant): ["あ\\い\\u26A0う\\\\u26A0え\\u26A0お","\u003Cx\u003E\u0026 \u0027 \u0022\u003C\/x\u003E"]

*/
20
26
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
26