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

вопрос создан в Mon, Oct 23, 2017 12:00 AM

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

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

Вот пример 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, что означает: Malformed UTF-8 символы, возможно, неправильно закодированные .

    
94
  1. В руководстве по PHP написано This function only works with UTF-8 encoded data., поэтому проблем с кодировкой не должно быть.
    2013-10-14 18: 37: 57Z
  2. Попробуйте использовать utf8_encode() в полях массива name, прежде чем передать строку в json_encode().
    2013-10-14 18: 43: 10Z
  3. Спасибо! Я просто пришел к этому решению, которое решило мою проблему.
    2013-10-14 18: 44: 16Z
  4. Да, видел ответ. Удачи.
    2013-10-14 18: 44: 57Z
  5. Используйте параметр JSON_PARTIAL_OUTPUT_ON_ERROR , чтобы увидеть проблему (например, поле с UTF8 будет нулевым).
    2016-05-29 18: 30: 58Z
13 ответов                              13                         

Через 2 часа копания (см. правку)

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

  • В моем случае это проблема с кодировкой
  • 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));

Примечание. utf8_encode () кодирует ISO-8859- 1 строка в UTF-8 согласно документам, так что если вы не уверены в кодировке ввода iconv () или mb_convert_encoding () могут быть лучшие варианты, как отмечено в комментариях и других решениях.

    
224
2019-04-19 03: 06: 27Z
  1. Спасибо за ваше решение ... однако, примечание с одной стороны: замените } else { на } else if (is_string ($d)) {; в противном случае все будет изменено на строки (например, INT станет STRING).
    2014-06-05 21: 36: 40Z
  2. Я хочу прямо сейчас вас обнять < 33
    2015-07-07 11: 55: 17Z
  3. Вы только что спасли мне жизнь. Я собирался закончить все, пока я не нашел эту функцию! Спасибо.
    2015-12-28 19: 33: 47Z
  4. WTF! Спасибо, что поделились своим решением. Я вижу, что для выяснения этого потребовалось бы немало усилий, и я благодарен вам за то, что вы это сделали и поделились.
    2016-04-04 23: 43: 19Z
  5. После трех дней отладки я могу поцеловать вас прямо сейчас.
    2016-04-23 02: 04: 46Z

Матье Риглер представил действительно хорошее решение, однако мне пришлось немного изменить его, чтобы обрабатывать и объекты:

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 ().

    
35
2015-02-02 23: 37: 01Z
  1. Разве это не должно быть elseif вместо else if? (т.е. без пробелов).
    2016-11-24 14: 00: 05Z
  2. @ UweKeim в соответствии с документацией PHP "elseif и else if, если будут считаться точно такими же, когда используются фигурные скобки", что означает, что они являются эквивалентами, пока вы не использовать нотацию двоеточия, например if(): elseif:
    2016-11-24 16: 30: 54Z
  3. Хорошая работа. PHP - это мусор, и такие парни, как вы, не дают ему идти на свалку.
    2017-01-18 16: 17: 02Z
  4. Вы должны вставить else if(is_int($d)||is_bool($d)) return $d; перед последним, потому что: {"success":true, "message":"Ⲃⲟⲟ𝓵ⲉⲁⲛ ⲁⲛⲇ Ⲓⲛϯⲉ𝓰ⲉꞅ𝛓"}
    2017-04-21 15: 31: 14Z
  5. Точно так же, как @ paul-peelen рекомендуется для @ matthieu-riegler: измените последний else на else if(is_string ($d)); в противном случае все будет изменено на строки (например, INT станет STRING).
    2017-09-02 13: 44: 34Z

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

например: $dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

    
23
2015-11-15 16: 28: 51Z
  1. это должен быть высоко оцененный /одобренный ответ, решающий проблемы в корне, хорошая работа
    2016-05-20 08: 39: 55Z
  2. Или в функциях mysqli: mysqli_set_charset ($connection, "utf8");
    2017-01-29 15: 19: 09Z
  3. Для меня это сработало и должно быть принятым ответом!
    2017-05-22 22: 06: 31Z
  4. Это был совет для моего решения. Немного другая причина подключения msqli. Просто позвоните $mysqli->set_charset("utf8"); после выполнения обработки вашей базы данных.
    2018-10-01 19: 16: 19Z

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

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

    return $d;
}
    
7
2015-09-29 08: 10: 41Z
  1. Мне нравится этот, поскольку он сохраняет ключи.
    2016-09-06 10: 40: 28Z

У меня точно такая же проблема на PHP 5.6. Я использую Открытый сервер + 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;
}
    
6
2018-01-21 00: 50: 45Z
  1. Для хинди урду и других региональных языков работает отлично, спасибо ...
    2019-05-05 10: 43: 24Z
  2. Отлично! - работает, если у вас есть массив объектов.
    2019-06-17 10: 26: 20Z

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

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

Обходное решение - это просто приведение к объекту перед кодированием, например:

json_encode((object)$myvar);
    
4
2016-04-15 16: 03: 12Z

Возвращение 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);
    
3
2013-10-14 18: 52: 58Z
  1. Это решение сработало для меня
    2017-01-02 07: 19: 04Z

Этот принятый ответ работает. Но в случае, если вы получаете данные из 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();
 }

LINK: http://php.net/manual/en/mysqli.set-charset.php р>     

3
2015-10-23 09: 55: 41Z

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

    
2
2016-12-22 07: 38: 53Z

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

$var = mb_convert_encoding($var, 'UTF-8');
    
2
2017-09-14 13: 54: 44Z

Я улучшил ответ Адама Бубелы. Я просто ненавижу, когда блоки не закрываются {и}. Это чище, и вы не представляете ошибок, или, может быть, я использовал 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;
    }
}

?>
    
1
2016-10-13 16: 40: 58Z

Если вы получаете эти данные из базы данных, используйте mysqli_set_charset($connection, "utf8"); в соединении, когда получите параметры из базы данных

    
0
2019-01-15 09: 49: 15Z

эта проблема возникает иногда - вы не проходите контроль доступа заголовка.

В моем случае, если бы я добавил какое-либо эхо до json_encode. Это показывало результат, иначе была пустая страница.

Я добавил

header('Access-Control-Allow-Origin: *'); 

и моя проблема решена.

    
0
2019-05-02 11: 44: 42Z
источник размещен Вот