Почему json_encode возвращает пустую строку

У меня есть простая структура php с 3 вложенными массивами.

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

Вот пример var_dump массива, который я хочу преобразовать в Json.

array (size=2) 'tram B' => array (size=2) 0 => array (size=3) 'name' => string 'Ile Verte' (length=9) 'distance' => int 298 'stationID' => int 762 1 => array (size=3) 'name' => string 'La Tronche Hôpital' (length=18) 'distance' => int 425 'stationID' => int 771 16 => array (size=4) 0 => array (size=3) 'name' => string 'Bastille' (length=8) 'distance' => int 531 'stationID' => int 397 1 => array (size=3) 'name' => string 'Xavier Jouvin' (length=13) 'distance' => int 589 'stationID' => int 438 

В другом скрипте у меня подобная структура, и json_encode отлично работает. Поэтому я не понимаю, почему json_encode не будет работать здесь.

Изменить: похоже, проблема с кодировкой. Когда mb_detect_encoding возвращает ASCII, json_encode работает, но когда он возвращает UTF8, он больше не работает.

Edit2: json_last_error() возвращает JSON_ERROR_UTF8 что означает: неверные символы UTF-8, возможно, неправильно закодированные .

Хорошо после 2 часов рытья (cf Edits)

Я узнал следующее:

  • В моем случае это проблема кодирования
  • mb_detect_encoding возвращает, вероятно, ошибочный ответ, некоторые строки, вероятно, не UTF-8
  • используя utf8_encode() на этой строке была решена моя проблема.

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

 function utf8ize($d) { if (is_array($d)) { foreach ($d as $k => $v) { $d[$k] = utf8ize($v); } } else if (is_string ($d)) { return utf8_encode($d); } return $d; } 

Используйте это просто так:

 echo json_encode(utf8ize($data)); 

Matthieu Riegler представил действительно хорошее решение, однако мне пришлось слегка модифицировать его для обработки объектов:

 function utf8ize($d) { if (is_array($d)) foreach ($d as $k => $v) $d[$k] = utf8ize($v); else if(is_object($d)) foreach ($d as $k => $v) $d->$k = utf8ize($v); else return utf8_encode($d); return $d; } 

Еще одно замечание: json_last_error () может быть полезным при отладке функций json_encode () / json_encode ().

Для меня ответ на эту проблему заключался в установке charset = utf8 в моем PDO-соединении.

ex: $dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

Adam Bubela также представил действительно хорошее решение, которое помогло мне решить мою проблему, и вот упрощенная функция:

 function utf8ize($d) { if (is_array($d) || is_object($d)) foreach ($d as &$v) $v = utf8ize($v); else return utf8_encode($d); return $d; } 

Возврат mb_detect_encoding может быть неправильным:

 $data = iconv('UTF-8', 'ISO-8859-1', 'La Tronche Hôpital'); var_dump( mb_detect_encoding($data), mb_detect_encoding($data, array('ISO-8859-1', 'UTF-8')) ); 

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

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

 $fromEncoding = 'ISO-8859-1'; // This depends on the data array_walk_recursive($array, function (&$value, $key, $fromEncoding) { if (is_string($value)) { $value = iconv($fromEncoding, 'UTF-8', $value); } }, $fromEncoding); 

Этот принятый ответ работает. Но в случае, если вы получаете данные из MySQL (как и я), есть более простой способ.

После того, как вы откроете свою базу данных, перед запросом вы можете установить набор символов с помощью mysqli следующим образом:

 /* change character set to utf8 | Procedural*/ if (!mysqli_set_charset($link, "utf8")) { printf("Error loading character set utf8: %s\n", mysqli_error($link)); exit(); } 

ИЛИ

 /* change character set to utf8 | Object Oriented*/ if (!$mysqli->set_charset("utf8")) { printf("Error loading character set utf8: %s\n", $mysqli->error); exit(); } 

ССЫЛКА: http://php.net/manual/en/mysqli.set-charset.php

Я столкнулся с этой проблемой на сервере, на котором установлена ​​более старая версия PHP (5.2). Я использовал флаг JSON_FORCE_OBJECT и, по-видимому, не поддерживался до 5.3

Поэтому, если вы используете этот флаг, обязательно проверьте свою версию!

Обходной путь, похоже, просто отличает объект перед кодированием, например:

 json_encode((object)$myvar); 

используя utf8_encode (), на этой строке была решена моя проблема.

Я улучшил ответ Адама Бубелы. Я просто ненавижу, когда блоки не закрыты {и}. Это чище, и вы не вводите ошибки или, может быть, это то, что я использовал Perl в прошлом 🙂

 <?php class App_Updater_String_Util { /** * Usage: App_Updater_String_Util::utf8_encode( $data ); * * @param mixed $d * @return mixed * @see http://stackoverflow.com/questions/19361282/why-would-json-encode-returns-an-empty-string */ public static function utf8_encode($d) { if (is_array($d)) { foreach ($d as $k => $v) { $d[$k] = self::utf8_encode($v); } } elseif (is_object($d)) { foreach ($d as $k => $v) { $d->$k = self::utf8_encode($v); } } elseif (is_scalar($d)) { $d = utf8_encode($d); } return $d; } } ?> 

Я получал данные от ob_get_clean () и имел ту же проблему, но выше решения не работают для меня. В моем случае это было решение, возможно, это поможет кому-то.

 $var = mb_convert_encoding($var, 'UTF-8');