Значения в UTF-8, закодированные как NULL в JSON

У меня есть набор ключевых слов, которые передаются через JSON из БД (кодированный UTF-8), некоторые из которых могут иметь специальные символы, такие как é, è, ç и т. Д. Это используется как часть автокомплексора. Пример:

array('Coffee', 'Cappuccino', 'Café'); 

Я должен добавить, что массив, исходящий из БД, будет:

 array('Coffee', 'Cappuccino', 'Café'); 

Но JSON кодирует как:

 ["coffee", "cappuccino", null]; 

Если я распечатаю их с помощью print_r (), они будут отображаться на веб-странице, кодированной UTF-8, но кафе появляется в виде «cafû, если используется текст / plain, если я хочу посмотреть на массив, используя print_r ($ array) ;Выход();.

Если я кодирую с помощью utf8_encode () перед кодировкой в ​​JSON, он проходит через штраф, но то, что печатается на веб-странице, является «кафе», а не «кафе».

Также странно, но json_last_error () рассматривается как неопределенная функция, но json_decode () и json_encode () работают нормально.

Любые идеи о том, как заставить кодированные данные UTF-8 из базы данных вести себя одинаково на протяжении всего процесса?

EIDT: Вот функция PHP, которая захватывает ключевые слова и превращает их в один массив:

 private function get_keywords() { global $db, $json; $output = array(); $db->query("SELECT keywords FROM listings"); while ($r = $db->get_array()) { $split = explode(",", $r['keywords']); foreach ($split as $s) { $s = trim($s); if ($s != "" && !in_array($s, $output)) $output[] = strtolower($s); } } $json->echo_json($output); } 

Метод json :: echo_json просто кодирует, устанавливает заголовок и печатает его (для использования с Prototype)

EDIT: DB Метод подключения:

 function connect() { if ($this->set['sql_connect']) { $this->connection = @mysql_connect( $this->set['sql_host'], $this->set['sql_user'], $this->set['sql_pass']) OR $this->debug( "Connection Error", mysql_errno() .": ". mysql_error()); $this->db = @mysql_select_db( $this->set['sql_name'], $this->connection) OR $this->debug( "Database Error", "Cannot Select Database '". $this->set['sql_name'] ."'"); $this->is_connected = TRUE; } return TRUE; } 

Дополнительные обновления: Простой скрипт PHP, который я запускал:

 echo json_encode( array("Café") ); // ["Caf\u00e9"] echo json_encode( array("Café") ); // null 

Причиной может быть настройка текущего клиента. Простым решением может быть установка клиента с помощью mysql_query('SET CHARACTER SET utf8') перед запуском запроса SELECT .

Обновление (июнь 2014 года)

Расширение mysql устарело от PHP 5.5.0. В настоящее время рекомендуется использовать mysqli. Кроме того, при дальнейшем прочтении – вышеуказанный способ настройки набора клиентов следует избегать по причинам, включая безопасность .

Я не тестировал его, но это должно быть заменой ok:

 $mysqli = new mysqli("localhost", "my_user", "my_password", "my_db"); if (!$mysqli->set_charset('utf8')) { printf("Error loading character set utf8: %s\n", $mysqli->error); } else { printf("Current character set: %s\n", $mysqli->character_set_name()); } 

или с параметром подключения:

 $conn = mysqli_connect("localhost", "my_user", "my_password", "my_db"); if (!mysqli_set_charset($conn, "utf8")) { # TODO - Error: Unable to set the character set exit; } 

Кажется, что json_encode строки, содержащие недопустимые символы. Вероятно, ваши данные UTF-8 не поступают в соответствующую форму из вашей базы данных.

Глядя на примеры, которые вы даете, моя дикая догадка заключается в том, что ваше соединение с базой данных не кодируется в кодировке UTF-8 и вместо этого служит символам ISO-8859-1.

Можете ли вы попробовать SET NAMES utf8; после инициализации соединения?

Я попробовал свой пример кода, как это

 [~]> cat utf.php <?php $arr = array('Coffee', 'Cappuccino', 'Café'); print json_encode($arr); [~]> php utf.php ["Coffee","Cappuccino","Caf\u00e9"] [~]> 

Исходя из этого, я бы сказал, что если исходные данные действительно UTF-8, то json_encode работает просто отлично. Если это не так, то вот где вы получите нуль. Почему его нет, я не могу сказать, основываясь на этой информации.

Попробуйте отправить массив через эту функцию перед выполнением json_encode ():

 <?php function utf8json($inArray) { static $depth = 0; /* our return object */ $newArray = array(); /* safety recursion limit */ $depth ++; if($depth >= '30') { return false; } /* step through inArray */ foreach($inArray as $key=>$val) { if(is_array($val)) { /* recurse on array elements */ $newArray[$key] = utf8json($inArray); } else { /* encode string values */ $newArray[$key] = utf8_encode($val); } } /* return utf8 encoded array */ return $newArray; } ?> 

Взято из комментария на phpnet @ http://php.net/manual/en/function.json-encode.php .

Функция в основном зацикливается на элементах массива, возможно, вы сделали свой код utf-8 в самом массиве?

Моим решением для кодирования данных utf8 было:

 $jsonArray = addslashes(json_encode($array, JSON_FORCE_OBJECT|JSON_UNESCAPED_UNICODE))