Unicode 6をサポートするPHPのUTF-8 JSONジェネレーター

もちろん、PHPには優れたjson_encode関数があります。 しかし、バージョン5.3までは、同じロシア文字が\ uXXXXの形式でエンコードされます-utf-8よりも何倍も長いです。 トラフィック量を減らすには、\ u-sequenceのutf-8文字変換を削除する必要があります。 はい。PHP5.4では、json_encodeがついにJSON_UNESCAPED_UNICODEパラメーターを取得しましたが、多くのホスティング事業者はバージョン5.2と5.3の間でのみ選択肢をユーザーに提供しています。



私は別の自転車を発明しませんでしたが、私が遭遇したこれらのソリューションには共通の問題があります-それらはユニコードベースプレーンのシンボルを正しく処理するだけです。



インターネット上で広く普及しているさまざまな修正方法では、json_encode関数の結果は、\ uXXXXのすべての出現をutf-8文字に置き換えるフィルターによって処理されます。 たとえば、次のように:



class Json{ static function json_encode($data){ return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function($val){ return mb_decode_numericentity('&#'.intval($val[1], 16).';', array(0, 0xffff, 0, 0xffff), 'utf-8'); }, json_encode($data) ); } }
      
      





そして、このコードは機能しました...それまでは、ユニコード絵文字のサポートを追加する必要が生じるまで(ユニコード6標準で絵文字が追加されました)、ほとんどのコードは0x1F000(最初のユニコードプレーン)以上です。



実際には、\ uシーケンスはutf-16でエンコードされます。コードごとに0x0000〜0xFFFF(「ウィンドウ」0xD800-0xDFFFを除く)の文字ごとのワード(2バイト)とコード0xD800-0xDFFFの2ワード(4バイト) 0xFFFFを超えるコードを持つ文字。



たとえば、utf-8表現 "\ xf0 \ x9f \ x98 \ x81"を持つコード0x1f601の元のUnicode文字は、json_dencode関数によって文字列 "\ ud83d \ ude01"に変換され、上記の関数の結果は文字列 "\ xed \ xa0 \ xbd \ xed \ xb8 \ x81 "。 1つの4バイト文字の代わりに、2つの3バイト文字が受信されました。



したがって、文字の通常の処理には、コードの分析と2文字\ uシーケンスの個別の変換が必要です。 たとえば、次のように:



 class Json{ static public $_code; static public function json_encode($data){ Json::$_code=0; return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function($val){ $val=hexdec($val[1]); if(Json::$_code){ $val=((Json::$_code&0x3FF)<<10)+($val&0x3FF)+0x10000; Json::$_code=0; }elseif($val>=0xD800&&$val<0xE000){ Json::$_code=$val; return ''; } return html_entity_decode(sprintf('&#x%x;', $val), ENT_NOQUOTES, 'utf-8'); }, json_encode($data) ); } }
      
      





このオプションは、utf-8文字を正しく変換します。



PS上記のコードは最適とはほど遠いことを完全に理解しています。 しかし、それは十分です-私のタスクのために-パフォーマンス。 そして、発明されたすべてのオプションの速度を比較するのは面倒です。 たとえば、分析を正規表現にシフトするオプションは次のとおりです。



 class Json{ static public function json_encode($data){ return preg_replace_callback('/\\\\ud([89ab][0-9a-f]{2})\\\\ud([cf][0-9a-f]{2})|\\\\u([0-9a-f]{4})/i', function($val){ return html_entity_decode( empty($val[3])? sprintf('&#x%x;', ((hexdec($val[1])&0x3FF)<<10)+(hexdec($val[2])&0x3FF)+0x10000): '&#x'.$val[3].';', ENT_NOQUOTES, 'utf-8' ); }, json_encode($data)); } }
      
      





PPS html_entity_decode呼び出しはコールバック関数に挿入されます。処理されたデータには、文字に変換されるべきではないユーティリティhtmlエンティティ( '<'、 '>'、 '&'など)を含むhtmlコードが含まれるためです。



All Articles