У меня простая структура 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, этого не происходит.
json_last_error() возвращает JSON_ERROR_UTF8, что означает: искаженные символы UTF-8, возможно, неправильно закодированные.
Ответ 1
У меня точно такая же проблема на PHP 5.6. Я использую Open Server + Nginx в Windows 7. Все кодировки установлены на UTF-8. Теоретически, согласно официальной документации, флаг JSON_UNESCAPED_UNICODE должен решить эту проблему. К сожалению, это не мой случай. Я не знаю почему. Все приведенные выше фрагменты не решают мою проблему, поэтому я нашел свою реализацию. Я считаю, что это могло бы кому-то помочь. По крайней мере, русские символы проходят проверку.
function utf8ize($d) {
if (is_array($d) || is_object($d)) {
foreach ($d as &$v) $v = utf8ize($v);
} else {
$enc = mb_detect_encoding($d);
$value = iconv($enc, 'UTF-8', $d);
return $value;
}
return $d;
}
Ответ 2
Этот принятый ответ работает. Но в случае, если вы получаете данные из MySQL (как я), есть более простой способ. После открытия базы данных перед запросом вы можете установить набор символов с помощью mysqli следующим образом:
/* изменить набор символов на utf8 | Процедурный подход*/
if (!mysqli_set_charset($link, "utf8")) {
printf("Ошибка загрузки символов из набора utf8: %s\n", mysqli_error($link));
exit();
}
или:
/* изменить набор символов на utf8 | Объектно-ориентированный подход*/
if (!$mysqli->set_charset("utf8")) {
printf("Ошибка загрузки символово из набора utf8: %s\n", $mysqli->error);
exit();
}
Ответ 3
Возврат 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'; // Это зависит от данных
array_walk_recursive($array, function (&$value, $key, $fromEncoding) {
if (is_string($value)) {
$value = iconv($fromEncoding, 'UTF-8', $value);
}
}, $fromEncoding);
Ответ 4
Это более лучшая версия кода из предыдущего ответа. Он чище, не привносит ошибок и может быть использован в Perl.
<?php
class App_Updater_String_Util {
/**
* Применение: App_Updater_String_Util::utf8_encode( $data );
*
* @param mixed $d
* @return mixed
*/
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;
}
}
?>
Web