O json_decode devolve null: como descobrir o que está mal no JSON

Quando o json_decode devolve null, o PHP sabe porquê: pergunte-lhe. A função json_last_error_msg() diz a razão em palavras, e quase sempre é uma de cinco: vírgula a mais, aspas simples, um carácter invisível no início, texto que não é UTF-8, ou uma resposta que nem sequer é JSON (uma página de erro, por exemplo).

Primeiro, perguntar ao PHP

<?php
$dados = json_decode($texto, true);
if ($dados === null && json_last_error() !== JSON_ERROR_NONE) {
  error_log('JSON: ' . json_last_error_msg());
  error_log('Início do texto: ' . substr($texto, 0, 200));
}

Registar também o início do texto é o que resolve a maioria dos casos: vê-se logo se começa por <html, por um aviso do PHP ou por um carácter estranho. Com PHP 7.3 ou superior pode usar a opção JSON_THROW_ON_ERROR e apanhar o erro com try/catch, em vez de testar a mão. Onde escrever esse registo está em escrever o seu próprio registo.

As causas, por ordem de frequência

A mensagem diz Causa Correcção
Syntax error Vírgula a mais antes de } ou ], aspas simples em vez de duplas, comentários, ou texto que não é JSON. O JSON só aceita aspas duplas e não aceita vírgula final nem comentários. Corrija na origem.
Syntax error, e o texto começa por um espaço estranho Um BOM (marca de ordem de bytes) no início do ficheiro, invisível no editor. Retire-o: $texto = ltrim($texto, "\xEF\xBB\xBF");. Melhor: grave o ficheiro «UTF-8 sem BOM».
Syntax error, e o texto começa por <br /> ou <b> Um aviso do PHP foi escrito antes do JSON. Corrija o aviso (veja o registo de erros do PHP) e não imprima nada antes do JSON.
Syntax error, e o texto começa por <!DOCTYPE A resposta é uma página HTML, em regra um erro 404 ou 500. Veja o código de estado do pedido antes de descodificar: chamar uma API com o cURL.
Malformed UTF-8 characters O texto vem em ISO-8859-1 ou noutra codificação. Converta com mb_convert_encoding($texto, 'UTF-8', 'ISO-8859-1') (a extensão mbstring) ou corrija a origem.
Maximum stack depth exceeded O JSON tem mais níveis do que o permitido. Raro. Aumente o terceiro argumento (a profundidade) ou simplifique a estrutura.

Quando o JSON é seu: o outro lado do problema

Se o PHP é que gera o JSON para uma página ou aplicação, os erros são os mesmos vistos ao contrário. Envie sempre o cabeçalho certo e não escreva nada antes:

<?php
header('Content-Type: application/json; charset=utf-8');
echo json_encode($resposta, JSON_UNESCAPED_UNICODE);

Um espaço ou uma linha em branco antes do <?php, ou depois de um ?> final, estraga a resposta. E se o json_encode devolver false, algum texto não está em UTF-8: veja a linha «Malformed UTF-8» do quadro acima.

Não «limpe» o JSON às cegas com expressões regulares. Remover caracteres até o json_decode deixar de reclamar esconde o problema e pode estragar dados verdadeiros. Descubra a causa com a mensagem e o início do texto, e corrija-a na origem.
Teste o texto fora do código. Colar o JSON num validador em linha mostra a linha e a coluna do erro. Não cole dados reais nem chaves em serviços de que não se fia.

Já tem a mensagem do json_last_error_msg e o início do texto, e ainda não percebe? Envie-nos os dois, sem chaves nem dados de clientes.

Abrir um pedido de suporte

VEJA TAMBÉM

Chamar uma API web a partir do PHP com o cURL

Escrever o seu próprio registo em PHP

Uma página em branco em PHP: como ver o erro

Onde está o registo de erros do PHP

PRODUTO RECOMENDADO

Alojamento de sites com cPanel

Domínio e SSL incluídos, cópias diárias e o painel que já conhece. desde 321,75 MT/mês (plano de 3 anos, com cupão)

Ver planos
  • 0 Utilizadores acharam útil
Esta resposta foi útil?