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) {
    // ...
}

Vous aimeriez progresser en PHP ? Mais vous ne savez pas comment vous y prendre ?

S'entraîner pour progresser en PHP

Mon programme "S'entraîner pour progresser en PHP" est disponible. Il vous permettra de recevoir chaque semaine un kata de code directement dans votre boîte mail, ainsi que des aides à la réalisation, des vidéos explicatives et des défis supplémentaires.

Reçois dès maintenant un kata gratuit en cliquant sur le bouton ci-dessous.