Подтвердить что ты не робот

Кодовые кодировки 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, но я бы предпочел, чтобы этого избежать.

4b9b3361

Ответ 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);
         }
      }
   }
}