Как сохранить json_encode () от удаления строк с недопустимыми символами

Есть ли способ удержать json_encode() от возврата null для строки, содержащей недопустимый символ (не UTF-8)?

Это может быть болью в заднице для отладки в сложной системе. Было бы гораздо более уместно увидеть недопустимый символ или, по крайней мере, его пропустить. Как бы то ни было, json_encode() будет молча отбрасывать всю строку.

Пример (в UTF-8):

 $string = array(utf8_decode("Düsseldorf"), // Deliberately produce broken string "Washington", "Nairobi"); print_r(json_encode($string)); 

Результаты в

 [null,"Washington","Nairobi"] 

Желаемый результат:

 ["D sseldorf","Washington","Nairobi"] 

Примечание . Я не ищу, чтобы сломанные строки работали в json_encode (). Я ищу способы облегчить диагностику ошибок кодирования. null строка для этого не помогает.

php пытается вызвать ошибку, но только если вы отключите display_errors . Это нечетно, потому что параметр display_errors предназначен только для контроля того, печатаются ли ошибки на стандартный вывод, а не при возникновении ошибки. Я хочу подчеркнуть, что когда вы используете display_errors , хотя вы можете видеть всевозможные другие php-ошибки, php не просто скрывает эту ошибку, но даже не запускает ее . Это означает, что он не будет отображаться в каких-либо журналах ошибок, и не будут вызваны какие-либо пользовательские error_handlers. Ошибка просто не возникает.

Вот какой код, который демонстрирует это:

 error_reporting(-1);//report all errors $invalid_utf8_char = chr(193); ini_set('display_errors', 1);//display errors to standard output var_dump(json_encode($invalid_utf8_char)); var_dump(error_get_last());//nothing ini_set('display_errors', 0);//do not display errors to standard output var_dump(json_encode($invalid_utf8_char)); var_dump(error_get_last());// json_encode(): Invalid UTF-8 sequence in argument 

Это странное и неудачное поведение связано с этой ошибкой https://bugs.php.net/bug.php?id=47494 и несколькими другими, и похоже, что это никогда не будет исправлено.

обходной путь:

Очистка строки перед ее передачей в json_encode может быть работоспособным решением.

 $stripped_of_invalid_utf8_chars_string = iconv('UTF-8', 'UTF-8//IGNORE', $orig_string); if ($stripped_of_invalid_utf8_chars_string !== $orig_string) { // one or more chars were invalid, and so they were stripped out. // if you need to know where in the string the first stripped character was, // then see http://stackoverflow.com/questions/7475437/find-first-character-that-is-different-between-two-strings } $json = json_encode($stripped_of_invalid_utf8_chars_string); 

http://php.net/manual/en/function.iconv.php

В руководстве говорится

//IGNORE молча отбрасывает символы, которые являются незаконными в целевой кодировке.

Поэтому, сначала удалив проблемные символы, теоретически json_encode () не должен получать что-либо, за что он задохнется и не сработает. Я не проверял, что вывод iconv с флагом //IGNORE отлично совместим с понятием json_encodes о том, какие действительные символы utf8 есть, поэтому покупатель остерегается … так как могут быть случаи кросс, где он все еще не работает. Я ненавижу проблемы с набором символов.

 $s = iconv('UTF-8', 'UTF-8//IGNORE', $s); 

Это решило проблему. Я не уверен, почему ребята из php не облегчили жизнь, установив json_encode() .

В любом случае использование вышеописанного позволяет json_encode () создавать объект, даже если данные содержат специальные символы (например, шведские буквы).

Затем вы можете использовать результат в javascript без необходимости декодирования данных обратно в исходную кодировку (с escape() , unescape() , encodeURIComponent() , decodeURIComponent() );

Я использую его так в php (smarty):

 $template = iconv('UTF-8', 'UTF-8//IGNORE', $screen->fetch("my_template.tpl")); 

Затем я отправляю результат в javascript и только innerHTML готовый шаблон (html peace) в моем документе.

Просто указанная выше строка должна быть реализована в json_encode() каким-то образом, чтобы позволить ей работать с любой кодировкой.

Эта функция удалит все недопустимые символы UTF8 из строки:

 function removeInvalidChars( $text) { $regex = '/( [\x00-\x7F] | [\xC0-\xDF][\x80-\xBF] | [\xE0-\xEF][\x80-\xBF]{2} | [\xF0-\xF7][\x80-\xBF]{3} ) | ./x'; return preg_replace($regex, '$1', $text); } 

Я использую его после преобразования документа Excel в json, поскольку документы Excel не гарантируются в UTF8.

Я не думаю, что есть особенно разумный способ преобразования недопустимых символов в видимый, но действительный символ. Вы можете заменить недействительные символы U + FFFD, который является символом замены Юникода, повернув регулярное выражение выше, но это действительно не обеспечивает лучшего пользовательского опыта, чем просто отбрасывание недопустимых символов.

Вам нужно знать кодировку всех строк, с которыми вы имеете дело, или вы входите в мир боли.

UTF-8 – это простая кодировка. Кроме того, JSON определен для использования UTF-8 (http://www.json.org/JSONRequest.html). Так почему бы не использовать его?

Короткий ответ: способ избежать json_encode () отбрасывания строк – убедиться, что они действительны UTF-8.

Вместо использования функции iconv вы можете использовать json_encode с параметром JSON_UNESCAPED_UNICODE (> = PHP5.4.0)

Убедитесь, что вы положили «charset = utf-8» в заголовок вашего php-файла:

header ('Content-Type: application / json; charset = utf-8');