JSON em PHP
Esta aula aborda o uso de JSON em PHP, incluindo as funções json_encode e json_decode, as flags disponíveis, a diferença entre objetos e arrays associativos e o tratamento de erros. O conteúdo inclui exemplos práticos, boas práticas e exercícios com respostas.
JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados, amplamente utilizado em APIs, configurações e comunicação entre sistemas. No PHP, o suporte a JSON é nativo, com funções simples e poderosas que permitem converter dados entre estruturas PHP e strings JSON. Nesta aula, vamos explorar as funções json_encode e json_decode, as flags que controlam o comportamento da serialização, as diferenças entre objetos e arrays associativos, e como lidar com erros de forma robusta.
Dominar JSON é essencial para qualquer desenvolvedor PHP moderno, pois é o formato padrão em serviços REST, integrações com JavaScript e armazenamento de dados estruturados. Vamos começar com o básico e avançar para técnicas mais refinadas, garantindo que você consiga usar JSON com confiança em seus projetos.
json_encode e json_decode
As duas funções principais para trabalhar com JSON em PHP são json_encode e json_decode. json_encode converte um valor PHP (arrays, objetos, strings, números, booleanos, null) em uma string JSON. json_decode faz o inverso: converte uma string JSON em um valor PHP.
Exemplo básico de json_encode:
<?php
$dados = [
'nome' => 'Maria',
'idade' => 30,
'email' => 'maria@example.com'
];
$json = json_encode($dados);
echo $json; // {"nome":"Maria","idade":30,"email":"maria@example.com"}
?>E o correspondente json_decode:
<?php
$json = '{"nome":"Maria","idade":30,"email":"maria@example.com"}';
$dados = json_decode($json);
var_dump($dados);
// object(stdClass)#1 (3) { ["nome"]=> string(5) "Maria" ["idade"]=> int(30) ["email"]=> string(17) "maria@example.com" }
?>Note que, por padrão, json_decode retorna objetos da classe stdClass quando o JSON contém objetos. Se você passar true como segundo argumento, ele retorna arrays associativos:
<?php
$dados = json_decode($json, true);
var_dump($dados);
// array(3) { ["nome"]=> string(5) "Maria" ["idade"]=> int(30) ["email"]=> string(17) "maria@example.com" }
?>Ambas as funções são essenciais para comunicação com APIs, armazenamento de dados em arquivos JSON e muito mais.
Flags
As funções json_encode e json_decode aceitam flags que alteram seu comportamento. Essas flags são constantes predefinidas do PHP, como JSON_PRETTY_PRINT, JSON_UNESCAPED_UNICODE, JSON_UNESCAPED_SLASHES, JSON_THROW_ON_ERROR, entre outras. Elas podem ser combinadas usando o operador pipe (|).
json_encode flags:
JSON_PRETTY_PRINT: formata a saída com espaços e quebras de linha, facilitando a leitura.JSON_UNESCAPED_UNICODE: não escapa caracteres Unicode (ex.: acentos), produzindo JSON com caracteres legíveis.JSON_UNESCAPED_SLASHES: não escapa barras (/), útil para URLs.JSON_NUMERIC_CHECK: converte strings numéricas em números.JSON_FORCE_OBJECT: força a saída como objeto, mesmo para arrays indexados.JSON_THROW_ON_ERROR: lança uma exceçãoJsonExceptionem caso de erro (disponível a partir do PHP 7.3).
Exemplo com JSON_PRETTY_PRINT e JSON_UNESCAPED_UNICODE:
<?php
$dados = [
'nome' => 'João',
'cidade' => 'São Paulo'
];
echo json_encode($dados, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>Saída:
{
"nome": "João",
"cidade": "São Paulo"
}json_decode flags:
JSON_OBJECT_AS_ARRAY: equivale a passartruecomo segundo argumento; retorna arrays associativos.JSON_BIGINT_AS_STRING: converte inteiros grandes em strings para evitar perda de precisão.JSON_THROW_ON_ERROR: lança exceção em caso de erro.
Exemplo com JSON_BIGINT_AS_STRING:
<?php
$json = '{"id": 12345678901234567890}';
$obj = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
echo $obj->id; // 12345678901234567890 (como string)
?>As flags permitem ajustar o comportamento às necessidades específicas, seja para legibilidade, compatibilidade ou desempenho.
Objetos vs arrays associativos
No PHP, arrays associativos e objetos são estruturas de dados diferentes, e isso se reflete na serialização JSON. Arrays associativos viram objetos JSON, enquanto arrays indexados viram arrays JSON. Objetos PHP (instâncias de classes) também viram objetos JSON, com suas propriedades.
Exemplo: array associativo vira objeto JSON:
<?php
$array = ['a' => 1, 'b' => 2];
echo json_encode($array); // {"a":1,"b":2}
?>Array indexado vira array JSON:
<?php
$array = [1, 2, 3];
echo json_encode($array); // [1,2,3]
?>Objeto PHP:
<?php
class Pessoa {
public $nome = 'Carlos';
public $idade = 25;
}
$p = new Pessoa();
echo json_encode($p); // {"nome":"Carlos","idade":25}
?>Ao decodificar, você pode escolher entre objeto ou array associativo. Objetos são úteis quando você quer acessar propriedades com sintaxe de objeto ($obj->prop), enquanto arrays associativos são mais convenientes para funções de array. A escolha depende do contexto.
Uma diferença importante: se você decodificar um objeto JSON como array associativo, as chaves podem ser acessadas como índices. Mas cuidado com chaves que são números: elas podem ser convertidas para inteiros em arrays, o que pode causar confusão. Nesse caso, usar objetos é mais seguro.
<?php
$json = '{"0": "zero", "1": "um"}';
$arr = json_decode($json, true);
var_dump($arr); // array(2) { [0]=> string(4) "zero" [1]=> string(3) "um" }
?>Isso pode ser um problema se você esperava chaves como strings. Para evitar isso, use JSON_OBJECT_AS_ARRAY com cuidado ou prefira objetos.
Tratamento de erros
Erros podem ocorrer ao codificar ou decodificar JSON: dados inválidos, profundidade máxima excedida, caracteres inválidos, etc. O PHP fornece a função json_last_error() que retorna o código do último erro, e json_last_error_msg() que retorna a mensagem. A partir do PHP 7.3, a flag JSON_THROW_ON_ERROR permite lançar uma exceção JsonException, facilitando o tratamento com try/catch.
Exemplo com json_last_error:
<?php
$json = '{"nome": "Maria"';
$dados = json_decode($json);
if (json_last_error() !== JSON_ERROR_NONE) {
echo 'Erro: ' . json_last_error_msg();
}
?>Com JSON_THROW_ON_ERROR, o código fica mais limpo:
<?php
try {
$dados = json_decode('{"nome": "Maria"', true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo 'Erro: ' . $e->getMessage();
}
?>Também é importante verificar o erro em json_encode. Por exemplo, se houver strings inválidas em UTF-8, a codificação pode falhar. Use JSON_INVALID_UTF8_SUBSTITUTE ou JSON_INVALID_UTF8_IGNORE para lidar com isso.
<?php
$dados = ['nome' => "\xB1\x31"]; // caractere inválido
$json = json_encode($dados, JSON_INVALID_UTF8_SUBSTITUTE);
echo $json; // {"nome":"�1"}
?>Adotar JSON_THROW_ON_ERROR é uma boa prática em código moderno, pois evita esquecimentos de verificação e torna o fluxo de erro mais explícito.
Boas práticas e observações finais
- Sempre valide a entrada JSON antes de usar, especialmente se ela vier de fontes externas.
- Use
JSON_UNESCAPED_UNICODEao gerar JSON para leitura humana, mas lembre-se de que isso pode aumentar o tamanho da string. - Prefira
JSON_THROW_ON_ERRORpara um tratamento de erros consistente. - Para arrays com chaves numéricas, esteja ciente do comportamento de conversão ao decodificar como array associativo.
- Ao trabalhar com APIs, defina o cabeçalho
Content-Type: application/jsonao enviar respostas. - Considere usar
JSON_PRETTY_PRINTapenas em ambientes de desenvolvimento, pois adiciona espaços desnecessários em produção.
Exercícios
- Escreva um script PHP que converte um array associativo em uma string JSON e exiba o resultado.
- Decodifique a string JSON
{"produto":"Notebook","preco":2999.90}como array associativo e imprima o preço. - Use
json_encodecom a flagJSON_PRETTY_PRINTpara formatar um array aninhado e exiba a saída. - Crie uma classe PHP com propriedades públicas e serialize-a para JSON. Depois, decodifique o JSON e acesse uma propriedade.
- Escreva um código que tenta decodificar um JSON inválido usando
JSON_THROW_ON_ERRORe captura a exceção, exibindo a mensagem de erro.
<?php
$dados = ['nome' => 'Ana', 'idade' => 28];
echo json_encode($dados);
?><?php
$json = '{"produto":"Notebook","preco":2999.90}';
$dados = json_decode($json, true);
echo $dados['preco']; // 2999.9
?><?php
$dados = [
'usuario' => [
'nome' => 'João',
'email' => 'joao@example.com'
]
];
echo json_encode($dados, JSON_PRETTY_PRINT);
?><?php
class Carro {
public $marca = 'Toyota';
public $ano = 2020;
}
$carro = new Carro();
$json = json_encode($carro);
$obj = json_decode($json);
echo $obj->marca; // Toyota
?><?php
try {
$json = '{"nome": "Maria"';
$dados = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo 'Erro: ' . $e->getMessage();
}
?>