Web

Почему 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, этого не происходит.

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

Как узнать, используется ли HTTPS без определения $_SERVER ['HTTPS']

Web

Почему move_uploaded_file выдает ошибку «Не удалось открыть поток: в доступе отказано»

Web

Как загрузить файл с помощью библиотеки Java HttpClient, работающей с PHP

Идеи и полезные книги по разработке высоконагруженных web-сервисов
Web

Идеи и полезные книги по разработке высоконагруженных web-сервисов