Récupérer l'erreur d'un json_decode

Lors de la transformation d'une chaîne json en tableau ou en objet, il peut être utile de connaître la raison d'une éventuelle erreur de décodage.

Par défaut, la méthode json_decode va retourner null si la chaîne n'a pas pu être décodée.

$var = '{"bad_json": "foo"';

$result = json_decode($var); // retourne null

Dans ce cas, pour récupérer un peu plus d'informations sur la raison de l'échec, vous pouvez utiliser les méthodes json_last_error() et json_last_error_msg().

$var = '{"bad_json": "foo"';

$result = json_decode($var);
if ($result === null) {
    echo "Error code: ", json_last_error().PHP_EOL;
    echo "Error message: ", json_last_error_msg().PHP_EOL;
}

Cela va afficher à l'écran :

Error code: 4
Error message: Syntax error

La liste complète des codes d'erreurs est visible directement sur le site de php.

Et pourquoi pas récupérer les erreurs via une exception ?

Depuis php 7.3, un flag a été rajouté dans les options de json_decode pour lever une exception en cas d'erreur.

$var = '{"bad_json": "foo"';

try {
    $result = json_decode($var, true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
    echo "Error code: ", $e->getCode().PHP_EOL;
    echo "Error message: ", $e->getMessage().PHP_EOL;
}

Et si votre chaîne vous paraît valide ?

J'ai eu le cas très récemment d'un json_decode qui retournait une Syntax error alors que la chaîne paraissait complètement valide quand je la logguais dans un fichier :

{"valid_json": "foo"}

Et après plusieurs tests, je me suis aperçus que la chaîne envoyée était en UTF8 avec BOM. Pour reproduire l'erreur :

$var = '{"valid_json": "foo"}';

// Ajout du BOM pour l'exemple
$var = chr(239).chr(187).chr(191).$var;

try {
    $result = json_decode($var, true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
    echo "Error code: ", $e->getCode().PHP_EOL;
    echo "Error message: ", $e->getMessage().PHP_EOL;
}

Si cela vous arrive, vous avez deux solutions :

  • Essayez de voir avec l'émetteur de la chaîne si elle ne peut pas être envoyée en UTF8 sans BOM
  • Si non, supprimer le BOM
$var = chr(239).chr(187).chr(191).'{"valid_json": "foo"}';

// Suppression du BOM
$bom = pack('H*','EFBBBF');
$var = preg_replace("/^$bom/", '', $var);

try {
    $result = json_decode($var, true, 512, JSON_THROW_ON_ERROR);
    var_dump($result);
} catch (\JsonException $e) {
    // ...
}

Cet article t'a plu ? Si oui, je te propose de t'inscrire à ma dev letter pour recevoir régulièrement dans ta boîte mail mes conseils, mes nouveaux articles, des vidéos à voir, des outils à découvrir et encore bien d’autres choses.

Je m'inscris