JSON (JavaScript Object Notation) é um modelo para armazenamento e transmissão de informações no formato texto. Apesar de muito simples, tem sido bastante utilizado por aplicações Web devido a sua capacidade de estruturar informações de uma forma bem mais compacta do que a conseguida pelo modelo XML, tornando mais rápido o parsing dessas informações.

O ambiente PHP, na versão 5.2.0 ou superior, oferece um parser bastante simples e interessante para a manipulação de dados estruturados no formato JSON. Basicamente, você precisa utilizar apenas três funções: “json_decode”, “json_encode”, e “json_last_error”. Para simplificar ainda mais as coisas, não é preciso realizar nenhuma instalação adicional ou qualquer tipo de configuração no “php.ini” para utilizar estas funções (as extensões para JSON são automaticamente compiladas quando instala-se o PHP).

2. Decodificando JSON: a função “json_decode”

A função “json_decode” recebe como entrada uma string codificada no formato JSON e a converte para uma variável PHP. Mostraremos como utilizar essa função através de alguns exemplos. Para começar, a Listagem 1 mostra um exemplo básico em que os dados de um funcionário (nome, idade e sexo) armazenados em uma string JSON são “importados” para um objeto PHP.

Listagem 1. Função “json_decode” – exemplo inicial


<?php
//string json contendo os dados de um funcionário
$json_str = '{"nome":"Jason Jones", "idade":38, "sexo": "M"}';

//faz o parsing na string, gerando um objeto PHP
$obj = json_decode($json_str);

//imprime o conteúdo do objeto 
echo "nome: $obj->nome<br>"; 
echo "idade: $obj->idade<br>"; 
echo "sexo: $obj->sexo<br>"; 
?> 

O resultado da execução do programa é:

nome: Jason Jones
idade: 38
sexo: M

Observe que a função “json_decode” é aplicada diretamente sobre a string “$json_str”, que contém os dados do funcionário representados em JSON. Esta função faz o parsing no conteúdo da string, convertendo-o automaticamente para um objeto PHP (variável $obj). Realizada a conversão, o $obj pode ser utilizada normalmente dentro do código PHP, conforme exemplificamos através das instruções “$echo”.

No exemplo apresentado, a string JSON possuía os dados de apenas um empregado. Mas como poderíamos proceder para trabalhar com uma string ou arquivo JSON contendo os dados de múltiplos empregados, como, por exemplo, os dados mostrados na Listagem 2.

Listagem 2. Arquivo JSON contendo 3 registros


{
empregados: 
[
{"nome":"Jason Jones", "idade":38, "sexo": "M"},
{"nome":"Ada Pascalina", "idade":35, "sexo": "F"},
{"nome":"Delphino da Silva", "idade":26, "sexo": "M"}
]
}' 

Quando desejamos representar múltiplos objetos em JSON, fazemos uso de um array. Os arrays JSON são delimitados por colchetes, com seus elementos separados entre vírgula, conforme mostrado na Listagem 2. Neste exemplo, os dados de três funcionários estão representados no array (“Jason Jones”, “Ada Pascalina” e “Delphino da Silva”). O programa da Listagem 3 demonstra como implementar um programa PHP para importar e trabalhar com um array JSON.

Listagem 3. Função “json_decode” –trabalhando com um object


<?php

//string json (array contendo 3 elementos)
$json_str = '{"empregados": '. 
		'[{"nome":"Jason Jones", "idade":38, "sexo": "M"},'.
		'{"nome":"Ada Pascalina", "idade":35, "sexo": "F"},'.
		'{"nome":"Delphino da Silva", "idade":26, "sexo": "M"}'.
		']}';

//faz o parsing da string, criando o array "empregados"
$jsonObj = json_decode($json_str);
$empregados = $jsonObj->empregados;

//navega pelos elementos do array, imprimindo cada empregado
foreach ( $empregados as $e )
    {
	echo "nome: $e->nome - idade: $e->idade - sexo: $e->sexo<br>"; 
    }
?> 

Veja o resultado da execução do programa:

nome: Jason Jones - idade: 38 - sexo: M
nome: Ada Pascalina - idade: 35 - sexo: F
nome: Delphino da Silva - idade: 26 - sexo: M


O exemplo da Listagem 4 mostra o parsing de uma srting JSON um pouco mais complexa. Desta vez, o primeiro funcionário possui dois dependentes, enquanto os demais não possuem (ou seja, foi introduzido um “campo” opcional denominado “dependentes”). Também acrescentamos uma nova variável denominada “data” para armazenar data da versão do arquivo de empregados.

Listagem 4. Função “json_decode” – trabalhando com um objeto complexo


<?php

//string json
//agora o primeiro empregado possui dependentes e os outros não.
//também foi acrescentado um campo denominado "data", contendo a data do arquivo de empregados
$json_str = '{"empregados": '. 
		'[{"nome":"Jason Jones", "idade":38, "sexo": "M", "dependentes": ["Sedna Jones", "Ian Jones"]},'.
		'{"nome":"Ada Pascalina", "idade":35, "sexo": "F"},'.
		'{"nome":"Delphino da Silva", "idade":26, "sexo": "M"}'.
		'],
		"data": "15/12/2012"}';

//faz o parsing da string, criando o array "empregados"
$jsonObj = json_decode($json_str);


//cria o array de empregados
$empregados = $jsonObj->empregados;

//imprime a data do arquivo e navega pelos elementos do array, imprimindo cada empregado. 
//caso o empregado possua dependentes, estes também são exibidos.
echo "<b>data do arquivo</b>: $jsonObj->data<br/>";
foreach ( $empregados as $e )
    {
	echo "nome: $e->nome - idade: $e->idade - sexo: $e->sexo<br/>"; 

	if (property_exists($e, "dependentes")) { 
		$deps = $e->dependentes;
		echo "dependentes: <br/>";
		foreach ( $deps as $d ) echo "- $d<br/>";
	}
    }
?> 

Observe que desta vez foi preciso tomar um cuidado adicional. Pelo fato de “dependentes” ser um campo opcional, foi preciso utilizar a função “property_exists” para checar cada empregado, ou seja para verificar se o $e (empregado corrente) possui uma propriedade denominada “dependentes”. Apenas em caso afirmativo que os dependentes são capturados (jogados para o array “$deps”) e exibidos na tela. O resultado da execução do programa é mostrado abaixo:

data do arquivo: 15/12/2012
nome: Jason Jones - idade: 38 - sexo: M
dependentes:
- Sedna Jones
- Ian Jones
nome: Ada Pascalina - idade: 35 - sexo: F
nome: Delphino da Silva - idade: 26 - sexo: M

A função “json_decode” possui uma opção bastante interessante que corresponde a gerar um array associativo a partir da string JSON. Para fazer isso, basta especificar o valor true, como segundo parâmetro na chamada da função, como mostra o exemplo da Listagem 5.

Listagem 5.Criando um array associativo com a função “json_decode”


<?php
//cria uma string no formato JSON
$json_str = '{"Jason":38,"Ada":35,"Delphino":26}';

//transforma a string em um array associativo
$json_arr = json_decode($json_str, true);

//exibe o array associativo
var_dump($json_arr);
?> 

Resultado:

array(3) { ["Jason"]=> int(38) ["Ada"]=> int(35) ["Delphino"]=> int(26) }

3. Codificando JSON: a função “json_encode”

Como o próprio nome indica, esta função faz o caminho inverso: ela converte um objeto PHP para uma string JSON. Um exemplo básico de utilização é apresentado na Listagem 6, onde transformamos um array associativo para uma string JSON.

Listagem 6. Função “json_encode” – exemplo inicial


<?php
//cria o array associativo
$idades = array("Jason"=>38, "Ada"=>35, "Delphino"=>26);

//converte o conteúdo do array associativo para uma string JSON
$json_str = json_encode($idades);

//imprime a string JSON
echo "$json_str";
?>

Veja abaixo o resultado da execução do programa:

{"Jason":38,"Ada":35,"Delphino":26}

Na Listagem 7, apresentamos um exemplo envolvendo um array mais complexo.

Listagem 7.Convertendo um array com 3 empregados para uma String JSON


<?php
//cria um array contendo 3 empregados
$empregados = array('empregados' => array(
    array(
        'nome' => 'Jason Jones',
        'idade' => 38,
        'sexo' => 'M'
    ),
    array(
        'nome' => 'Ada Pascalina',
        'idade' => 35,
        'sexo' => 'F'
    ),
    array(
        'nome' => 'Delphino da Silva',
        'idade' => 26,
        'sexo' => 'M'
    )));

//converte o conteúdo do array para uma string JSON
$json_str = json_encode($empregados);

//imprime a string JSON
echo "$json_str";
?>

Como resultado, é gerada a seguinte string JSON:

{"empregados":[{"nome":"Jason Jones","idade":38,"sexo":"M"}, {"nome":"Ada Pascalina","idade":35,"sexo":"F"}, {"nome":"Delphino da Silva","idade":26,"sexo":"M"}]}

OBS: A Listagem 7 apresentou a conversão de uma estrutura complexa representada em um array. Porém, é importante esclarecer que também é possível converter objetos (instâncias de classes PHP) com o uso da função “json_encode”.

4. Tratamento de Erros

Para realizar o tratamento de erros o PHP disponibiliza a função “json_last_error”. Esta função simplesmente retorna uma das seguintes constantes pré-definidas para indicar o erro ocorrido.

  • 0 = JSON_ERROR_NONE: nenhum erro ocorreu;
  • 1 = JSON_ERROR_DEPTH: a profundidade máxima de aninhamento de uma string JSON foi excedida (esse valor máximo é 512);
  • 2 = JSON_ERROR_STATE_MISMATCH: erro de underflow ou outro tipo de estado inválido;
  • 3 = JSON_ERROR_CTRL_CHAR: foi encontrado um caractere de controle no corpo da string JSON;
  • 4 = JSON_ERROR_SYNTAX: erro de sintaxe;
  • 5 = JSON_ERROR_UTF8: erro na codificação UTF-8 da string JSON;

Um exemplo de código para tratamento de erros é mostrado na Listagem 8. Neste exemplo, deixamos propositalmente sem aspas o valor da variável sexo (M). Com isto, um erro de sintaxe (JSON_ERROR_SYNTAX) será acusado pela função “json_last_error”.

Listagem 8. Função “json_last_error”


<?php
//string json contendo os dados de um funcionário. 
//esta string não está bem-formada, pois o valor M não está entre aspas
$json_str = '{"nome":"Jason Jones", "idade":38, "sexo": M}';

//faz o parsing na string, gerando um objeto PHP
$obj = json_decode($json_str);

//testa se houve erro no parsing! Vai acusar erro de string mal-formada (JSON_ERROR_SYNTAX)
if (json_last_error() == 0) {
    echo '- Nao houve erro! O parsing foi perfeito';
}	
else {			
    echo 'Erro!</br>';
	switch (json_last_error()) {
	
        case JSON_ERROR_DEPTH:
            echo ' - profundidade maxima excedida';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - state mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Caracter de controle encontrado';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Erro de sintaxe! String JSON mal-formada!';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Erro na codificação UTF-8';
        break;
        default:
            echo ' – Erro desconhecido';
        break;
    }
}
?> 

Veja o resultado:

Erro!
- Erro de sintaxe! String JSON mal-formada!

Este artigo apresentou as três funções básicas que podemos utilizar na linguagem PHP para a manipulação de dados no formato JSON. Como comentário final, é importante que você perceba que estas funções trabalham importando as informações JSON para a memória. Normalmente isto não gera nenhum problema, pois o principal uso do JSON é a troca mensagens de tamanho pequeno ou médio entre aplicações, quase sempre com o uso da tecnologia AJAX. Se você precisar trabalhar com um arquivo JSON de tamanho muito grande, precisará procurar por alguma extensão desenvolvida por terceiros.