json_decode возвращает JSON_ERROR_SYNTAX, но он-лайн форматировщик говорит, что JSON в порядке

19

У меня возникла очень странная проблема.

У меня есть веб-сервис JSON.

Когда я проверю его с помощью этого веб-сайта http://www.freeformatter.com/json-formatter.html#ad-output

Все в порядке.

Но когда я загружаю свой JSON с помощью этого кода:

  $data = file_get_contents('http://www.mywebservice');

if(!empty($data))
{

    $obj = json_decode($data);

 switch (json_last_error()) {
    case JSON_ERROR_NONE:
        echo ' - JSON_ERROR_NONE';
    break;
    case JSON_ERROR_DEPTH:
        echo ' - JSON_ERROR_DEPTH';
    break;
    case JSON_ERROR_STATE_MISMATCH:
        echo ' - JSON_ERROR_STATE_MISMATCH';
    break;
    case JSON_ERROR_CTRL_CHAR:
        echo ' -  JSON_ERROR_CTRL_CHAR';
    break;
    case JSON_ERROR_SYNTAX:
        echo "\r\n\r\n - SYNTAX ERROR \r\n\r\n";
    break;
    case JSON_ERROR_UTF8:
        echo ' - JSON_ERROR_UTF8';
    break;
    default:
        echo ' - Unknown erro';
    break;
}

Я получил ошибку: SYNTAX ERROR

КОТОРЫЙ НЕ ПОМОГАЕТ ПОЛНОМ ВСЕМ.

Это кошмар.

Я вижу, что с помощью PHP 5.5 я мог бы использовать эту функцию: http://php.net/manual/en/function.json-last-error-msg.php

(но мне еще не удалось установить PHP 5.5, и я не уверен, что эта функция даст мне больше деталей)

  • 3
    Пожалуйста, покажите JSON.
  • 0
    JSON, пожалуйста. Нам нужен ваш JSON.
Показать ещё 1 комментарий
Теги:

7 ответов

53

Я столкнулся с той же проблемой, на самом деле есть невидимые скрытые символы, и вам нужно удалить их. Вот глобальный код, который работает во многих случаях:

<?php
$checkLogin = file_get_contents("http://yourwebsite.com/JsonData");

// This will remove unwanted characters.
// Check http://www.php.net/chr for details
for ($i = 0; $i <= 31; ++$i) { 
    $checkLogin = str_replace(chr($i), "", $checkLogin); 
}
$checkLogin = str_replace(chr(127), "", $checkLogin);

// This is the most common part
// Some file begins with 'efbbbf' to mark the beginning of the file. (binary level)
// here we detect it and we remove it, basically it the first 3 characters 
if (0 === strpos(bin2hex($checkLogin), 'efbbbf')) {
   $checkLogin = substr($checkLogin, 3);
}

$checkLogin = json_decode( $checkLogin );
print_r($checkLogin);
?>
  • 2
    Уважаемый сэр, вы понятия не имеете, насколько это помогло мне. Я везде искал решение и почти сдался. Сэр, вы находка.
  • 0
    Все еще задаюсь вопросом, почему это не является частью основного PHP версии 7.0.x. (лицо ладонью)
Показать ещё 3 комментария
26

Удаление спецификации (отметка байтового байта) часто - это необходимое вам решение:

function removeBOM($data) {
    if (0 === strpos(bin2hex($data), 'efbbbf')) {
       return substr($data, 3);
    }
    return $data;
}

У вас нет спецификации, но если она там, она невидима, поэтому вы ее не увидите!!

см. W3C в спецификации в HTML

используйте BOM Cleaner, если у вас есть много файлов для исправления.

  • 0
    Я изменил кодировку с UTF-8 UTF-8 without BOM Notepad++ из top menu of Notepad++>Format>UTF-8 without BOM
  • 0
    Потерял почти 1 час, пытаясь миллион вещей, прежде чем найти этот ответ ... спасибо куча!
Показать ещё 1 комментарий
15

Я решил эту проблему добавить stripslashes в строку, перед json_decode.

$data = stripslashes($data); 
$obj = json_decode($data);
  • 1
    Пожалуйста, отформатируйте ваш код. Благодарю.
  • 3
    это не должно быть $ data = stripslashes ($ data);
3

Чтобы собрать все вещи здесь и там, я подготовил JSON-обертку с автоматическими корректирующими действиями декодирования.

abstract class Json
{
    public static function getLastError($asString = FALSE)
    {
        $lastError = \json_last_error();

        if (!$asString) return $lastError;

        // Define the errors.
        $constants = \get_defined_constants(TRUE);
        $errorStrings = array();

        foreach ($constants["json"] as $name => $value)
            if (!strncmp($name, "JSON_ERROR_", 11))
                $errorStrings[$value] = $name;

        return isset($errorStrings[$lastError]) ? $errorStrings[$lastError] : FALSE;
    }

    public static function getLastErrorMessage()
    {
        return \json_last_error_msg();
    }

    public static function clean($jsonString)
    {
        if (!is_string($jsonString) || !$jsonString) return '';

        // Remove unsupported characters
        // Check http://www.php.net/chr for details
        for ($i = 0; $i <= 31; ++$i)
            $jsonString = str_replace(chr($i), "", $jsonString);

        $jsonString = str_replace(chr(127), "", $jsonString);

        // Remove the BOM (Byte Order Mark)
        // It the most common that some file begins with 'efbbbf' to mark the beginning of the file. (binary level)
        // Here we detect it and we remove it, basically it the first 3 characters.
        if (0 === strpos(bin2hex($jsonString), 'efbbbf')) $jsonString = substr($jsonString, 3);

        return $jsonString;
    }

    public static function encode($value, $options = 0, $depth = 512)
    {
        return \json_encode($value, $options, $depth);
    }

    public static function decode($jsonString, $asArray = TRUE, $depth = 512, $options = JSON_BIGINT_AS_STRING)
    {
        if (!is_string($jsonString) || !$jsonString) return NULL;

        $result = \json_decode($jsonString, $asArray, $depth, $options);

        if ($result === NULL)
            switch (self::getLastError())
            {
                case JSON_ERROR_SYNTAX :
                    // Try to clean json string if syntax error occured
                    $jsonString = self::clean($jsonString);
                    $result = \json_decode($jsonString, $asArray, $depth, $options);
                    break;

                default:
                    // Unsupported error
            }

        return $result;
    }
}

Пример использования:

$json_data = file_get_contents("test.json");
$array = Json::decode($json_data, TRUE);
var_dump($array);
echo "Last error (" , Json::getLastError() , "): ", Json::getLastError(TRUE), PHP_EOL;
  • 0
    Я целый день боролся со странно закодированным файлом, содержащим JSON, и этот класс наконец-то дал мне полезный массив PHP - спасибо!
  • 0
    Работал для меня как шарм! Огромное спасибо!!
1

Вы не показываете свой JSON, но это звучит так, как будто это может быть недопустимая последовательность UTF-8 в аргументе, большинство онлайн-валидаторов не поймают ее. убедитесь, что ваши данные UTF-8, а также проверьте наличие у вас иностранных символов. Вам не нужен PHP5, чтобы увидеть вашу ошибку, используйте error_log() для регистрации проблем.

0

У меня была такая же проблема. Для меня это вызывало echo "<br/><pre>".

Я пытался передать строку json в другой php файл, используя:

exit(json_encode(utf8ize($resp_array)));

В начале файла я разделил тег разрыва строки... Так что это была ошибка для меня. Удалив этот тег разделительной линии, я смог [...]

  • 0
    это не та проблема, которая описана в вопросе, но это очень распространенная проблема, и ее трудно обнаружить, поэтому полезно упомянуть ее.
0

У меня была такая же проблема. Для меня это вызывало echo "<br/><pre>". Я пытался передать строку json в другой php файл, используя exit(json_encode(utf8ize($resp_array)));. В начале файла я упустил тег break line... Так что это была ошибка для меня. Удалив этот тег break line, я смог декодировать мою строку json другим файлом php.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню