2009-02-24 24 views
67

jsonを使用してリソースを表現するWebサービスを作成しています.Jsonをエンコードする最善の方法について考えています。 json rfc(http://www.ietf.org/rfc/rfc4627.txt)を読むと、好ましいエンコーディングはutf-8であることが明らかです。しかしrfcは、文字を指定するための文字列エスケープメカニズムも記述しています。私はこれが非アスキー文字をエスケープするために一般に使用されると仮定し、結果としてutf-8を有効なasciiにします。JSON文字エンコーディング - ブラウザでうまくサポートされているUTF-8ですか、それとも数値エスケープシーケンスを使用する必要がありますか?

私は、非ASCII文字のUnicode文字(コードポイント)を含むjson文字列を持っているとしましょう。私のwebserviceはutf-8をエンコードして返しますか、それともASCII以外の文字をエスケープして純粋なasciiを返すべきですか?

私は、ブラウザがjsonpまたはevalを使用して結果を実行できるようにしたいと考えています。それは決定に影響しますか? utf-8のさまざまなブラウザのjavascriptサポートに関する私の知識は欠けています。

EDIT:結果をエンコードする方法に関する私の主な懸念は、実際に結果のブラウザ処理に関するものであることを明確にしたかったのです。私が読んだところでは、特にJSONPを使用している場合、ブラウザがエンコーディングに敏感である可能性があります。私はその件について本当に良い情報が見つからなかったので、何が起こるかを見るためにいくつかのテストをやり始めなければなりません。理想的には、必要な文字をエスケープしたいだけで、utf-8は結果をエンコードします。

答えて

63

JSONの仕様が必要とするすべてのJSONパーサは、適切なUTF-8だけでだけでなく、数値エスケープシーケンスを処理することができます。

JSONエンコーダが数字のエスケープシーケンスを使用できるようになるだけで、より多くの選択肢が提供されます。数字のエスケープシーケンスを選択する理由の1つは、のエンコーダーと目的のデコーダの間のトランスポートメカニズムがバイナリセーフではない場合です。

JSONコードはHTMLまたは誤ってブラウザにエスケープせずに配置されている場合、HTMLシーケンスとして解釈することができるあなたがストリームに登場する特定の文字を防ぐために、数値エスケープシーケンスであることがもう一つの理由、など<&"、これをHTMLとして解釈します。これは、HTMLインジェクションやクロスサイトスクリプティングに対する防御になります(注意:一部の文字は、"\を含むJSONでエスケープしなければなりません)。

PHPのJSON実装であるなど、常にのようなフレームワークでは、ASCII以外の文字のエンコーダ側で数値エスケープシーケンスを実行します。これは、制限されたトランスポートメカニズムなどとの最大限の互換性を目的としています。ただし、これはJSONデコーダがUTF-8に問題があることを示すものではありません。

だから、私はあなただけでこのように使用するかを決めることができると思います:

  • エンコーダとデコーダとの間保管や輸送のあなたの方法はバイナリデータに対応していない場合を除きだけで、UTF-8を使用します。

  • それ以外の場合は、数値エスケープシーケンスを使用します。

10

ASCIIはそれ以上存在しません。 UTF-8エンコーディングを使用すると、ASCIIエンコーディングを使用していないことを意味します。 固相線を逆に、引用符を、そして:

すべてのUnicode文字が エスケープしなければならない文字のため 除く引用符で を配置することができる:何のためのエスケープ機構を使用する必要がありますすることはRFCが言うことです制御文字 (U + 001FによるU + 0000)

+0

あなたが指定した引用符を読めば、すべてのユニコード文字をエスケープする必要はなく、少数の特殊文字しか表示されないことがわかります。しかし、結果をエンコードする必要があります(できればutf-8)。だから問題は「あなたがutf-8エンコーディングをしているなら、なぜ普通のUnicode文字をエスケープするのか」ということです。 – schickb

+0

また、asciiでエンコードされた文字列は、utf-8の純粋なサブセットです。 jsonのエスケープ文字をASCII以外のすべての文字に使用すると、結果はascii - したがってutf-8になります。様々なjsonライブラリ(python simplejsonのような)にはascii結果を強制するモードがあります。私は、おそらくブラウザでの実行のような理由で推測します。 – schickb

+0

普通のユニコード文字をエスケープするのは、文字列のようなメタキャラクターのコンテキストにあります。 (私が引用したRFCのチャンクは文字列に関するものですが、残念ですが、そのことについてはっきりしていませんでした)。ASCII出力を常に行う必要はありません。私はそれが壊れたブラウザでのデバッグのためだと思います。 – chaos

14

私はそこに問題がありました。 JSONが "é"のような文字列をエンコードすると、すべてのブラウザは "é"を返します。IE以外は "\ u00e9"を返します。

PHP json_decode()で "é"が見つかると失敗します。Firefox、Opera、Safari、Chromeの場合は、json_decode()の前にutf8_encode()を呼び出しています。

注:私のテストでは、IEとFirefoxはネイティブJSONオブジェクトを使用していますが、他のブラウザではjson2.jsを使用しています。

+10

おそらくあなたは 'utf8_encode()'を意味していました。http://php.net/manual/en/function.utf8-encode.php – Binyamin

+4

IEがそれを解読できないのであれば、使用しているJSONデコーダのバグです。すべてのJSONデコーダは、エンコードされたフォームを正常にデコードする必要があります。または、JSONデコーダではありません。エスケープされていないjson_decode()の問題に関しては、それを与えるテキストはUTF-8ではない可能性があります。 JSONデコーダは、たとえPHPが通常他の多くの関数でUTF-8を想定していなくても、PHP実装さえUTF-8を前提としています。エスケープされていない、画面上では全く同じように見えるが、UTF-8ではない他の文字エンコーディングがあります。 \ uXXXX形式のエンコーディングはこれを回避する方法です。 – thomasrutter

+0

JSONは合法的にUnicodeエンコーディング(UTF-8、UTF-16 BE/LE、UTF32 BE/LE、バイトオーダーマーカーの有無にかかわらず)で入力できます。また、ASCIIはUTF-8のサブセットであるため、ASCIIで入力することもできます。たとえばパーサーがUTF-32を受け入れるかどうかはわかりません。 – gnasher729

0

私はécharと同様の問題を抱えていました...私は「あなたがそれを供給しているテキストがUTF-8ではない可能性があります」とコメントしています。私は、私のインスタンスのデフォルトの照合は、私が実現してutf8に変更されるまで何か他のものだったと感じています...データは既にそこにあったので、データを変換したかどうかはわかりません。ワークベンチ。最終的な結果は、PHPはデータをエンコードせず、falseを返すだけです。私の問題の原因となっているサーバとしてどのブラウザを使用しても問題ありません。phpはこの文字が存在する場合、utf8にデータを解析しません。それは、データが存在した後にスキーマをutf8に変換するか、単なるPHPバグかによるものかどうかは分かりません。この場合、使用するjson_encode(utf8_encode($string));

3

私は同じ問題に直面していました。わたしにはできる。これを確認してください。

json_encode($array,JSON_UNESCAPED_UNICODE); 
関連する問題