2

スクリプトでは、cURLを使用してデータを送信し、CURLOPT_RETURNTRANSFERを有効にしました。応答はjsonでエンコードされたデータです。json_decodeを実行しようとすると、nullが返されます。次に、応答の文字列の先頭にutf-8 BOM記号が含まれていることがわかりました()。

いくつかの実験があります:


$data = $data = curl_exec($ch);
echo $data;

結果は{"field_1": "text_1"、 "field_2": "text_2"、 "field_3":"text_3"}です。

$data = $data = curl_exec($ch);
echo mb_detect_encoding($data);

結果-UTF-8

$data = $data = curl_exec($ch);
echo mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
// identical to echo mb_convert_encoding($data, 'UTF-8', 'UTF-8');

結果-{"field_1": "text_1"、 "field_2": "text_2"、 "field_3": "text_3"}


役立つ1つのことは、最初の3つのシンボルを削除することです。

if (substr($data, 0, 3) == pack('CCC', 239, 187, 191)) {
    $data = substr($data, 3);
}

しかし、別のBOMがある場合はどうなるでしょうか。したがって、問題は次のとおりです。cURL応答の正しいエンコーディングを検出する方法は?または、どのBOMが到着したかを検出する方法は?または、BOMを使用して応答を変換する方法はありますか?

4

3 に答える 3

5

あなたはすでに自分で答えを見つけたのではないかと思います-私が知っているより良い答えがないという点で悪いニュースです。

BOMはそこにあるべきではなく、それを一緒に送信しないのは送信者の責任です。

しかし、私はあなたを安心させることができます、BOMはそこにあるか存在しないかのどちらかです、そしてもしそうなら、それはあなたが知っているそれらの3バイトです。

少し速くして、小さな変更で別のNBOMを処理できます。

$__BOM = pack('CCC', 239, 187, 191);
// Careful about the three ='s -- they're all needed.
while(0 === strpos($data, $__BOM))
    $data = substr($data, 3);

サードパーティのBOM検出器は何も変わりません。このようにして、後でcURLが不要なBOMを削除し始めた場合でもカバーされます。

考えられる原因

一部のJSONオプティマイザーとフィルターは、出力にBOMが必要であると判断する場合があります。また、おそらくもっと簡単に言えば、JSONを生成するスクリプトを書いた人は誰でも、PHPの開始タグの前に誤ってBOMを含めていました。Apacheは、BOMが何であるかを気にせず、開始タグの前にデータがあることを確認するため、データを送信してPHPストリーム自体から非表示にします。これにより、「ヘッダーを追加できません:出力はすでに開始されています」というエラーが発生することもあります。

コンテンツの検出

JSONが有効なUTF-8、BOM、またはBOMではないことを確認できますが、mb_stringサポートが必要であり、いくつかのエッジケースを取得するには厳密モードを使用する必要があります

if (false === mb_detect_encoding($data, 'UTF-8', true)) {
    // JSON contains invalid sequences (erroneously NOT JSON encoded)
}

考えられるエンコーディングエラーを修正しようとしないことをお勧めします。自分のコードを壊したり、他の人の作業を維持しなければならないリスクがあります。

于 2012-09-20T09:49:00.610 に答える
0

このページでは、同様の問題について詳しく説明しています。Wordpressによって自動生成されたPHPページのBOM

基本的に、JSONジェネレーターがPHPで記述されていて、エディターが開始<?phpタグの前に何らかの形でBOMに忍び込んでいる場合に発生する可能性があります。あなたのクライアント言語はPHPなので、これが適切だと思います。

substr比較を使用してそれを取り除くことができます-BOMはドキュメントの先頭でのみ発生します。ただし、JSONソースを制御できる場合は、代わりにソースドキュメントからBOMを削除する必要があります。

于 2012-09-20T09:48:21.373 に答える
0

There will never be more than 3 characters before the "{". Those 3 characters are one character in UTF-8. So if you just do $data = substr($data, 3); you will be fine.

Take a look here for more information: json_decode returns NULL after webservice call

于 2012-09-20T09:50:37.317 に答える