cURL получает ответ с помощью спецификации utf-8

В моем сценарии я отправляю данные с помощью cURL и включаю CURLOPT_RETURNTRANSFER. Ответ – это json-кодированные данные. Когда я пытаюсь json_decode, он возвращает null. Затем я обнаружил, что ответ содержит символы спецификации utf-8 в начале строки (ï »¿).

Есть несколько экспериментов:


$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 "}


Единственное, что помогает – удалить первые 3 символа:

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

Но что, если будет другая спецификация? Поэтому возникает вопрос: как определить правильное кодирование ответа cURL? ИЛИ как определить, какая спецификация появилась? Или, может быть, как преобразовать ответ с помощью спецификации?

Боюсь, что вы уже нашли ответ самостоятельно – это плохая новость в том, что лучшего ответа я не знаю.

Спецификация не должна быть там, и ответственность отправителя не должна посылать ее.

Но я могу вас успокоить, спецификация есть либо там, либо нет, и если да, это те три байта, которые вы знаете.

У вас может быть немного быстрее и обрабатывать другие N спецификаций с небольшим изменением:

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

Независимый детектор спецификации не будет отличаться. Таким образом, вы закрыты, даже если позднее cURL начал снимать ненужные спецификации.

Возможные причины

Некоторые оптимизаторы и фильтры JSON могут решить, что для вывода требуется спецификация. Кроме того, возможно, более просто, тот, кто написал сценарий, генерирующий JSON, непреднамеренно включал спецификацию перед открывающим тегом PHP. Apache, не заботясь о том, что такое спецификация, видит, что перед открывающим тегом есть данные, поэтому отправляет их и скрывает от самого потока PHP. Иногда это может привести к ошибке «Не удается добавить заголовки: вывод уже запущен».

Обнаружение контента

Вы можете проверить, что JSON действителен UTF-8, спецификация или не спецификация, но нужна поддержка mb_string и вы должны использовать строгий режим, чтобы получить некоторые кромки:

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

Я бы посоветовал не пытаться исправить возможную ошибку кодирования; вы рискуете нарушить свой собственный код, а также должны поддерживать чужую работу.

Эта страница описывает аналогичную проблему: спецификация на странице PHP, автоматически созданная WordPress

В принципе, это может произойти, когда генератор JSON написан на PHP, и редактор каким-то образом пробрался в спецификации перед открывающим <?php . Поскольку ваш клиентский язык является PHP, я предполагаю, что это актуально.

Вы можете разбить его, используя сравнение substr – спецификация только когда-либо встречается в начале документа. Но если у вас есть контроль над источником JSON, вы должны удалить спецификацию из исходного документа.

Перед «{» никогда не будет больше 3 символов. Эти 3 символа являются одним символом в UTF-8. Итак, если вы просто делаете $ data = substr ($ data, 3); с тобой все будет в порядке.

Взгляните сюда для получения дополнительной информации: json_decode возвращает NULL после вызова webservice