Debug de API na prática: por que seu JSON está retornando com erro?
\n\nVocê já se pegou às três da manhã, olhando para uma tela vazia do Postman e pensando: "Por que meu script PHP está retornando HTML em vez de JSON?"? Se sim, você não está sozinho. O tópico Returning JSON from a PHP Script no Stack Overflow acumula dezenas de milhares de visualizações, e não é por acaso. Quase todo desenvolvedor backend iniciante comete os mesmos erros: headers esquecidos, saída com lixo, Content-Type incorreto.
\n\nNeste artigo, não vamos apenas copiar respostas de fóruns. Vamos analisar como retornar JSON do PHP de forma correta, rápida e sem surpresas. Você descobrirá por que exit(json_encode($data)) pode te decepcionar, como economizar milissegundos na serialização e o que fazer quando o JSON simplesmente "quebra".
Pronto? Vamos nessa.
\n\nAnatomia de uma resposta JSON correta
\n\nVamos começar pelo básico. Veja como não fazer:
\n\n<?php\n$data = ['status' => 'ok', 'message' => 'Olá!'];\necho json_encode($data);\n?>\n\nPor que isso é ruim? Primeiro, não há o header Content-Type. O navegador ou cliente pode interpretar a resposta como HTML ou texto. Segundo, se houver qualquer espaço em branco, echo ou warning antes no código, o JSON será corrompido.
O template mínimo correto é assim:
\n\n<?php\nheader('Content-Type: application/json; charset=utf-8');\n$data = ['status' => 'ok', 'message' => 'Olá!'];\necho json_encode($data, JSON_UNESCAPED_UNICODE);\nexit;\n?>\n\nObserve o JSON_UNESCAPED_UNICODE — ele mantém os caracteres acentuados legíveis, em vez de transformá-los em \\u00E9\\u00E7\\u00E3o. E o exit é uma proteção contra saídas acidentais após a resposta.
Headers: não só Content-Type
\n\nPara otimizar a performance do JSON, adicione mais alguns headers:
\n\nheader('Content-Type: application/json; charset=utf-8');\nheader('X-Content-Type-Options: nosniff');\nheader('Cache-Control: no-cache, must-revalidate');\n\nX-Content-Type-Options: nosniff impede o navegador de "adivinhar" o tipo de conteúdo — é segurança. E Cache-Control é útil para dados dinâmicos, evitando que o cliente armazene em cache uma resposta desatualizada.
Tratamento de erros: quando o JSON_ENCODE falha
\n\nA função json_encode retorna false em caso de falha. E é aqui que a coisa fica interessante. Se você simplesmente fizer echo json_encode($data) e receber uma string vazia como resposta, o cliente ficará confuso.
Sempre verifique o resultado:
\n\n$json = json_encode($data, JSON_UNESCAPED_UNICODE);\nif ($json === false) {\n http_response_code(500);\n echo json_encode(['error' => 'Falha na codificação JSON: ' . json_last_error_msg()]);\n exit;\n}\necho $json;\nexit;\n\nA propósito, json_last_error_msg() retorna uma mensagem clara: "Malformed UTF-8 characters" ou "Inf and NaN cannot be JSON encoded". Isso pode salvar horas de debug.
Dados profundamente aninhados e recursão
\n\nOutro problema são referências cíclicas em objetos. Se você passar um objeto com referências mútuas, o json_encode lançará um erro. Solução: use JSON_PARTIAL_OUTPUT_ON_ERROR ou converta o objeto em array previamente.
$json = json_encode($complexObject, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR);\n\nMas cuidado: a saída parcial pode ser incompleta. O ideal é corrigir a estrutura dos dados.
\n\nOtimização de performance do JSON em PHP
\n\nAgora vamos ao que realmente importa — como acelerar o retorno de JSON do PHP.
\n\n1. Cache do JSON serializado
\n\nSe os dados mudam com pouca frequência (catálogos, configurações, lista de cidades), não os serialize toda vez. Salve o JSON pronto em um arquivo, Memcached