Кодовые кодировки UTF-8 json_encode()
Quest
Я хочу получить строки с акцентированными символами. Кодировка для столбца (NAME
) составляет latin1_swedish_ci
.
Код
Следующий запрос возвращает Abord â Plouffe
с помощью phpMyAdmin:
SELECT C.NAME FROM CITY C
WHERE C.REGION_ID=10 AND C.NAME_LOWERCASE LIKE '%abor%'
ORDER BY C.NAME LIMIT 30
Ниже отображаются ожидаемые значения (функция называется db_fetch_all( $result )
):
while( $row = mysql_fetch_assoc( $result ) ) {
foreach( $row as $value ) {
echo $value . " ";
$value = utf8_encode( $value );
echo $value . " ";
}
$r[] = $row;
}
Отображаемые значения: 5482 5482 Abord â Plouffe Abord â Plouffe
Затем массив кодируется с помощью json_encode
:
$rows = db_fetch_all( $result );
echo json_encode( $rows );
Проблема
Веб-браузер получает следующее значение:
{"ID":"5482","NAME":null}
Вместо:
{"ID":"5482","NAME":"Abord â Plouffe"}
(Или закодированный эквивалент.)
Вопрос
В документации указано, что json_encode()
работает в UTF-8. Я могу видеть, что значения кодируются от LATIN1 до UTF-8. Однако после вызова json_encode()
значение становится null
.
Как мне сделать json_encode()
правильно закодировать значения UTF-8?
Одним из возможных решений является использование Zend Framework, но я бы предпочел, чтобы этого избежать.
Ответы
Ответ 1
// Create an empty array for the encoded resultset
$rows = array();
// Loop over the db resultset and put encoded values into $rows
while($row = mysql_fetch_assoc($result)) {
$rows[] = array_map('utf8_encode', $row);
}
// Output $rows
echo json_encode($rows);
Ответ 2
foreach( $row as $value ) {
$value = utf8_encode( $value );
Фактически вы не записываете свое закодированное значение в массив $row
, вы меняете только локальную переменную $value
. Если вы хотите записать обратно при изменении переменной, вам нужно будет обработать ее как ссылку:
foreach( $row as &$value ) {
Лично я старался избегать ссылок там, где это возможно, и для этого случая вместо этого используйте array_map
как опубликовано Kemo.
Или mysql_set_charset
в UTF-8, чтобы получить возвращаемые значения в UTF-8, независимо от фактических сопоставлений таблицы, в качестве первого шага к переносу приложения в UTF-8.
Ответ 3
Мое решение вставляет эту строку mysql_query('SET CHARACTER SET utf8');
перед SELECT
.
Этот метод хорош.
Ответ 4
Кажется, что вместо того, чтобы помещать его в запрос, нужно поставить:
mysql_set_charset('utf8');
после инструкции mysql connect.
Ответ 5
В вашем подключении: mysql_set_charset('utf8', $link);
Пример:
<?php
$link = mysql_connect('localhost', 'your_user', 'your_password');
mysql_set_charset('utf8', $link);
$db_selected = mysql_select_db('your_db', $link);
...
Надеюсь, что это помогает.
Ответ 6
Попробуйте iconv_r($row,"LATIN1","UTF-8//TRANSLIT");
(функция ниже) перед тем, как вы json_encode()
получите результат.
У меня есть UTF-8 в качестве кодировки таблицы и как кодировка результирующего набора, но иногда люди все еще могут отправлять символы без UTF-8 через формы, и это затрудняет отслеживание каждого источника входных данных, поэтому я также обернул json_encode()
, чтобы сделать его более безопасным. В частности, у меня на нем были NULL строки, содержащие символ степени и "умные кавычки", которые так любят люди в Великобритании.
function safe_json_encode($mixed,$missing="TRANSLIT"){
$out=json_encode($mixed);
if ($err= json_last_error()){
iconv_r("UTF-8","UTF-8//$missing",$mixed);
$out=json_encode($mixed);
}
return $out;
}
function iconv_r($charset_i, $charset_o, &$mixed) {
if (is_string($mixed)) {
$mixed = iconv($charset_i, $charset_o, $mixed);
} else {
if (is_object($mixed)){
$mixed = (array) $mixed;
}
if (is_array($mixed)){
foreach ($mixed as $key => &$value) {
iconv_r($charset_i, $charset_o, $value);
}
}
}
}