web-dev-qa-db-fra.com

json_decode retourne JSON_ERROR_SYNTAX mais le formateur en ligne dit que le JSON est OK

J'ai un problème très étrange.

J'ai un service Web JSON.

Quand je vérifie avec ce site http://www.freeformatter.com/json-formatter.html#ad-output

Tout va bien.

Mais quand je charge mon JSON avec ce code:

  $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;
}

J'ai eu l'erreur: SYNTAX ERROR

QUEL IS N'AIDE PAS PLEIN AT TOUT.

C'est un cauchemar. 

Je vois qu'avec PHP 5.5 je pourrais utiliser cette fonction: http://php.net/manual/en/function.json-last-error-msg.php

(mais je n'ai pas encore réussi à installer PHP 5.5, et je ne suis pas sûr que cette fonction me donnera plus de détails)

26

J'ai rencontré le même problème, en fait il y a des caractères cachés invisibles et vous devez les supprimer . Voici un code global qui fonctionne dans de nombreux cas:

<?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's the first 3 characters 
if (0 === strpos(bin2hex($checkLogin), 'efbbbf')) {
   $checkLogin = substr($checkLogin, 3);
}

$checkLogin = json_decode( $checkLogin );
print_r($checkLogin);
?>
64
Kris Khairallah

Supprimer la variable BOM (Byte Order Mark) est souvent la solution dont vous avez besoin:

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

Vous ne devriez pas avoir de nomenclature, mais si elle est là, elle est invisible pour ne pas la voir !!

voir W3C sur les nomenclatures en HTML

utilisez BOM Cleaner si vous avez beaucoup de fichiers à réparer.

39
Greg Rundlett

J'ai résolu ce problème en ajoutant stripslashes à la chaîne avant json_decode.

$data = stripslashes($data); 
$obj = json_decode($data);
24
hobbito

Pour rassembler toutes ces choses ici et là, j'ai préparé une enveloppe JSON avec le décodage des actions correctives automatiques. La version la plus récente se trouve dans mon GitHub Gist .

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's 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's 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;
    }
}

Exemple d'utilisation:

$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;
6
Krzysztof Przygoda

Vous n'avez pas montré votre code JSON, mais cela donne l'impression qu'il pourrait s'agir d'une séquence UTF-8 non valide en argument, la plupart des validateurs en ligne ne l'auront pas capturé. Assurez-vous que vos données sont au format UTF-8 et vérifiez également si vous avez des caractères étrangers. Vous n'avez pas besoin de PHP5 pour voir votre erreur, utilisez error_log () pour enregistrer les problèmes.

1
meda

Après avoir essayé toute la solution sans le résultat c'est celui qui a fonctionné pour moi.

J'espère que ça va aider quelqu'un

$data = str_replace('&quot;', '"', $data);
0
Bheru Lal Lohar