🐘 PHP & JSON

💡 Funções Principais

O PHP oferece duas funções principais para trabalhar com JSON: json_encode() para converter PHP em JSON e json_decode() para converter JSON em PHP.

Visão Geral

Função Descrição Entrada Saída
json_encode() Converte PHP para JSON Array/Object PHP String JSON
json_decode() Converte JSON para PHP String JSON Array/Object PHP

📤 json_encode()

Converte um valor PHP (array, objeto, etc.) numa string JSON.

Sintaxe

Sintaxe
string json_encode(mixed $value, int $flags = 0, int $depth = 512)

Conversão Básica

Array para JSON
<?php
// Array associativo
$pessoa = [
    'nome' => 'Ana Silva',
    'idade' => 28,
    'ativo' => true
];

$json = json_encode($pessoa);
echo $json;
// {"nome":"Ana Silva","idade":28,"ativo":true}

// Array indexado
$cores = ['vermelho', 'verde', 'azul'];
echo json_encode($cores);
// ["vermelho","verde","azul"]
?>

Tipos de Conversão

PHP JSON
['a', 'b'] (array indexado) ["a","b"]
['key' => 'val'] (array associativo) {"key":"val"}
true / false true / false
null null
123 (int) 123
12.34 (float) 12.34

Objetos PHP

Objeto para JSON
<?php
class Utilizador {
    public $nome;
    public $email;

    public function __construct($nome, $email) {
        $this->nome = $nome;
        $this->email = $email;
    }
}

$user = new Utilizador('João', 'joao@exemplo.com');
echo json_encode($user);
// {"nome":"João","email":"joao@exemplo.com"}
?>

JSON Formatado (Legível)

JSON_PRETTY_PRINT
<?php
$data = [
    'nome' => 'Maria',
    'idade' => 30,
    'hobbies' => ['ler', 'correr']
];

// Sem formatação
echo json_encode($data);
// {"nome":"Maria","idade":30,"hobbies":["ler","correr"]}

// Formatado (legível)
echo json_encode($data, JSON_PRETTY_PRINT);
/*
{
    "nome": "Maria",
    "idade": 30,
    "hobbies": [
        "ler",
        "correr"
    ]
}
*/
?>

📥 json_decode()

Converte uma string JSON num valor PHP.

Sintaxe

Sintaxe
mixed json_decode(
    string $json,
    bool $associative = false,
    int $depth = 512,
    int $flags = 0
)

Para Array vs Objeto

Array Associativo vs Objeto
<?php
$json = '{"nome":"Ana","idade":25}';

// Para objeto (padrão)
$obj = json_decode($json);
echo $obj->nome;  // "Ana"
echo $obj->idade; // 25

// Para array associativo (recomendado)
$arr = json_decode($json, true);
echo $arr['nome'];  // "Ana"
echo $arr['idade']; // 25
?>
💡 Dica

Usa sempre json_decode($json, true) para obter um array associativo. É mais fácil de trabalhar em PHP do que objetos stdClass.

Arrays JSON

Decoding Arrays
<?php
// Array simples
$json = '["vermelho","verde","azul"]';
$arr = json_decode($json, true);
print_r($arr);
// Array ( [0] => vermelho [1] => verde [2] => azul )

// Array de objetos
$json = '[{"id":1,"nome":"Ana"},{"id":2,"nome":"Bruno"}]';
$arr = json_decode($json, true);
foreach ($arr as $item) {
    echo $item['nome'] . "\n";
}
// Ana
// Bruno
?>

Aceder a Valores Aninhados

Acesso Aninhado
<?php
$json = '{
    "empresa": {
        "nome": "TechCorp",
        "funcionarios": [
            {"nome": "Ana", "cargo": "Dev"},
            {"nome": "Bruno", "cargo": "Designer"}
        ]
    }
}';

$data = json_decode($json, true);

// Aceder a valores
echo $data['empresa']['nome'];                    // TechCorp
echo $data['empresa']['funcionarios'][0]['nome']; // Ana
echo $data['empresa']['funcionarios'][1]['cargo']; // Designer

// Contar elementos
echo count($data['empresa']['funcionarios']);     // 2
?>

⚙️ Opções e Flags

Flags do json_encode()

Flag Descrição
JSON_PRETTY_PRINT Formata JSON com indentação (legível)
JSON_UNESCAPED_UNICODE Não escapa caracteres Unicode
JSON_UNESCAPED_SLASHES Não escapa barras /
JSON_NUMERIC_CHECK Converte strings numéricas para números
JSON_FORCE_OBJECT Força output como objeto
JSON_PRESERVE_ZERO_FRACTION Preserva decimais .0 em floats

Exemplos Práticos

Flags em Ação
<?php
$data = [
    'nome' => 'João',
    'url' => 'https://exemplo.com/pagina',
    'preco' => 10.0
];

// Sem flags
echo json_encode($data);
// {"nome":"Jo\u00e3o","url":"https:\/\/exemplo.com\/pagina","preco":10}

// Com flags
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
/*
{
    "nome": "João",
    "url": "https://exemplo.com/pagina",
    "preco": 10
}
*/

// Preservar zero fraction
echo json_encode($data, JSON_PRESERVE_ZERO_FRACTION);
// {"nome":"João","url":"https://exemplo.com/pagina","preco":10.0}
?>

Combinar Flags

Combinar Múltiplas Flags
<?php
$data = ['nome' => 'José', 'caminho' => 'C:\\Users\\Jose'];

// Combinação comum
$json = json_encode(
    $data,
    JSON_PRETTY_PRINT |
    JSON_UNESCAPED_UNICODE |
    JSON_UNESCAPED_SLASHES
);
?>

🚨 Tratamento de Erros

Detetar Erros

Verificar Erros
<?php
// json_encode retorna false em caso de erro
$json = json_encode($data);

if ($json === false) {
    echo "Erro JSON: " . json_last_error_msg();
}

// json_decode retorna null em caso de erro
$data = json_decode($jsonString, true);

if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
    echo "JSON inválido: " . json_last_error_msg();
}
?>

Funções de Erro

Função Retorna
json_last_error() Código do último erro (int)
json_last_error_msg() Mensagem do erro (string)

Códigos de Erro

Erros Comuns
<?php
// JSON_ERROR_NONE = 0 (sem erros)
// JSON_ERROR_DEPTH = 1 (profundidade máxima excedida)
// JSON_ERROR_STATE_MISMATCH = 2 (JSON mal formado)
// JSON_ERROR_CTRL_CHAR = 3 (caractere de controlo inválido)
// JSON_ERROR_SYNTAX = 4 (erro de sintaxe)
// JSON_ERROR_UTF8 = 5 (caracteres UTF-8 inválidos)

$json = '{"nome": "João"'; // JSON incompleto

$data = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    switch (json_last_error()) {
        case JSON_ERROR_SYNTAX:
            echo "Erro de sintaxe no JSON";
            break;
        case JSON_ERROR_UTF8:
            echo "Caracteres UTF-8 inválidos";
            break;
        default:
            echo "Erro: " . json_last_error_msg();
    }
}
?>

Função Segura

Função de Decodificação Segura
<?php
function safeJsonDecode(string $json, bool $assoc = true) {
    $data = json_decode($json, $assoc);

    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception(
            "JSON inválido: " . json_last_error_msg(),
            json_last_error()
        );
    }

    return $data;
}

// Uso
try {
    $data = safeJsonDecode('{"nome":"Ana"}');
    echo $data['nome']; // Ana
} catch (Exception $e) {
    echo "Erro: " . $e->getMessage();
}
?>

📁 Ler e Escrever Ficheiros

Escrever JSON em Ficheiro

Guardar JSON
<?php
$data = [
    'utilizadores' => [
        ['id' => 1, 'nome' => 'Ana', 'email' => 'ana@exemplo.com'],
        ['id' => 2, 'nome' => 'Bruno', 'email' => 'bruno@exemplo.com']
    ],
    'total' => 2
];

// Converter para JSON formatado
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

// Guardar em ficheiro
file_put_contents('utilizadores.json', $json);

echo "Ficheiro guardado com sucesso!";
?>

Ler JSON de Ficheiro

Ler JSON
<?php
// Ler ficheiro
$json = file_get_contents('utilizadores.json');

if ($json === false) {
    die("Erro ao ler ficheiro");
}

// Decodificar
$data = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    die("JSON inválido: " . json_last_error_msg());
}

// Usar dados
foreach ($data['utilizadores'] as $user) {
    echo $user['nome'] . " - " . $user['email'] . "\n";
}
?>

Configurações

Ficheiro de Configuração
<?php
// config.json
/*
{
    "app_name": "Minha App",
    "debug": true,
    "database": {
        "host": "localhost",
        "name": "mydb",
        "user": "root"
    }
}
*/

// Carregar configuração
function loadConfig(string $file): array {
    if (!file_exists($file)) {
        throw new Exception("Ficheiro de config não encontrado");
    }

    $json = file_get_contents($file);
    $config = json_decode($json, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception("Config inválida: " . json_last_error_msg());
    }

    return $config;
}

$config = loadConfig('config.json');
echo $config['database']['host']; // localhost
?>

🌐 API REST

Criar API JSON

Endpoint API
<?php
// api.php
header('Content-Type: application/json');

// Simular dados
$utilizadores = [
    ['id' => 1, 'nome' => 'Ana', 'email' => 'ana@exemplo.com'],
    ['id' => 2, 'nome' => 'Bruno', 'email' => 'bruno@exemplo.com'],
    ['id' => 3, 'nome' => 'Carla', 'email' => 'carla@exemplo.com']
];

// Rota: GET /api.php
$method = $_SERVER['REQUEST_METHOD'];

if ($method === 'GET') {
    // Retornar todos os utilizadores
    echo json_encode([
        'success' => true,
        'data' => $utilizadores,
        'count' => count($utilizadores)
    ]);
} else {
    http_response_code(405);
    echo json_encode([
        'success' => false,
        'error' => 'Método não permitido'
    ]);
}
?>

Receber JSON de API

POST com JSON
<?php
// api.php - Receber JSON
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Ler body do pedido
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        http_response_code(400);
        echo json_encode([
            'success' => false,
            'error' => 'JSON inválido'
        ]);
        exit;
    }

    // Validar dados
    if (!isset($data['nome']) || !isset($data['email'])) {
        http_response_code(422);
        echo json_encode([
            'success' => false,
            'error' => 'Nome e email são obrigatórios'
        ]);
        exit;
    }

    // Processar dados...
    $novoId = rand(100, 999);

    // Resposta de sucesso
    http_response_code(201);
    echo json_encode([
        'success' => true,
        'data' => [
            'id' => $novoId,
            'nome' => $data['nome'],
            'email' => $data['email']
        ],
        'message' => 'Utilizador criado com sucesso'
    ]);
}
?>

📝 Exercícios

▼

Exercício 1: Codificar Array

Problema: Converte este array PHP para JSON formatado:

$produto = [
    'id' => 101,
    'nome' => 'Laptop',
    'preco' => 899.99,
    'disponivel' => true
];
<?php
$produto = [
    'id' => 101,
    'nome' => 'Laptop',
    'preco' => 899.99,
    'disponivel' => true
];

$json = json_encode($produto, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo $json;
/*
{
    "id": 101,
    "nome": "Laptop",
    "preco": 899.99,
    "disponivel": true
}
*/
?>
▼

Exercício 2: Decodificar JSON

Problema: Decodifica este JSON e mostra o nome do segundo utilizador:

[{"id":1,"nome":"Ana"},{"id":2,"nome":"Bruno"},{"id":3,"nome":"Carla"}]
<?php
$json = '[{"id":1,"nome":"Ana"},{"id":2,"nome":"Bruno"},{"id":3,"nome":"Carla"}]';

$utilizadores = json_decode($json, true);

echo $utilizadores[1]['nome']; // Bruno

// Ou com loop
foreach ($utilizadores as $user) {
    echo $user['nome'] . "\n";
}
?>
▼

Exercício 3: Validação

Problema: Cria uma função que valida JSON e retorna o array ou mensagem de erro.

<?php
function validarJson(string $json): array {
    $data = json_decode($json, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        return [
            'valido' => false,
            'erro' => json_last_error_msg()
        ];
    }

    return [
        'valido' => true,
        'data' => $data
    ];
}

// Teste
$resultado = validarJson('{"nome":"Ana"}');
if ($resultado['valido']) {
    print_r($resultado['data']);
} else {
    echo "Erro: " . $resultado['erro'];
}
?>