Introduzione
Quando si lavora con JSON in PHP, uno degli aspetti più utili e allo stesso tempo più delicati è la gestione di strutture annidate: oggetti dentro oggetti, array dentro array, e combinazioni miste tra dati numerici e associativi. Questo scenario è molto comune in API, configurazioni, payload di form complessi, risposte di servizi esterni e dati provenienti da frontend moderni.
Il problema non è solo leggere o scrivere JSON, ma farlo in modo ordinato, sicuro e manutenibile. Se il JSON contiene più livelli, accedere ai valori senza controlli può generare errori, warning o dati incompleti. In questo tutorial vedremo come gestire strutture complesse in PHP usando json_decode(), accesso protetto ai dati, trasformazioni mirate e ricostruzione del JSON finale.
L’obiettivo è imparare un approccio pratico: partire da un JSON reale, estrarre i dati utili, validarli e trasformarli in una struttura più comoda da usare nel codice PHP.
Codice completo
<?php
declare(strict_types=1);
/**
* Esempio di gestione di un JSON annidato:
* - decodifica sicura
* - accesso a dati profondi
* - validazione minima
* - trasformazione in una struttura più semplice
* - ricodifica finale in JSON
*/
$jsonInput = ´{
"ordine": {
"id": 1042,
"cliente": {
"nome": "Luca",
"email": "[email protected]",
"indirizzo": {
"citta": "Milano",
"cap": "20100"
}
},
"articoli": [
{
"sku": "BK-001",
"nome": "Libro PHP Avanzato",
"quantita": 2,
"prezzo": 24.90
},
{
"sku": "MN-778",
"nome": "Mouse Wireless",
"quantita": 1,
"prezzo": 19.99
}
],
"spedizione": {
"metodo": "corriere",
"costo": 6.50
}
}
}´;
// 1) Decodifica con controllo errori
$data = json_decode($jsonInput, true, 512, JSON_THROW_ON_ERROR);
// 2) Estrazione sicura dei valori annidati
$ordine = $data[´ordine´] ?? null;
if (!is_array($ordine)) {
throw new RuntimeException(´Struttura JSON non valida: chiave "ordine" mancante.´);
}
$cliente = $ordine[´cliente´] ?? [];
$indirizzo = $cliente[´indirizzo´] ?? [];
$articoli = $ordine[´articoli´] ?? [];
$spedizione = $ordine[´spedizione´] ?? [];
// 3) Validazione minima dei campi fondamentali
$nomeCliente = $cliente[´nome´] ?? ´´;
$emailCliente = $cliente[´email´] ?? ´´;
if ($nomeCliente === ´´ || $emailCliente === ´´) {
throw new RuntimeException(´Dati cliente incompleti.´);
}
if (!filter_var($emailCliente, FILTER_VALIDATE_EMAIL)) {
throw new RuntimeException(´Email cliente non valida.´);
}
if (!is_array($articoli) || count($articoli) === 0) {
throw new RuntimeException(´L´ordine deve contenere almeno un articolo.´);
}
// 4) Calcolo totale ordine con gestione dei dati numerici
$totaleArticoli = 0.0;
$rigaArticoli = [];
foreach ($articoli as $articolo) {
if (!is_array($articolo)) {
continue;
}
$sku = $articolo[´sku´] ?? ´N/D´;
$nome = $articolo[´nome´] ?? ´Prodotto sconosciuto´;
$quantita = (int)($articolo[´quantita´] ?? 0);
$prezzo = (float)($articolo[´prezzo´] ?? 0);
if ($quantita <= 0 || $prezzo < 0) {
continue;
}
$subtotale = $quantita * $prezzo;
$totaleArticoli += $subtotale;
$rigaArticoli[] = [
´sku´ => $sku,
´nome´ => $nome,
´quantita´ => $quantita,
´prezzo´ => $prezzo,
´subtotale´ => round($subtotale, 2),
];
}
$costoSpedizione = (float)($spedizione[´costo´] ?? 0);
$totaleOrdine = $totaleArticoli + $costoSpedizione;
// 5) Creazione di una struttura pulita per output o salvataggio
$output = [
´ordine_id´ => (int)($ordine[´id´] ?? 0),
´cliente´ => [
´nome´ => $nomeCliente,
´email´ => $emailCliente,
´citta´ => $indirizzo[´citta´] ?? null,
´cap´ => $indirizzo[´cap´] ?? null,
],
´articoli´ => $rigaArticoli,
´spedizione´ => [
´metodo´ => $spedizione[´metodo´] ?? ´non specificato´,
´costo´ => round($costoSpedizione, 2),
],
´totali´ => [
´articoli´ => round($totaleArticoli, 2),
´ordine´ => round($totaleOrdine, 2),
],
];
// 6) Ricodifica in JSON leggibile
$jsonOutput = json_encode(
$output,
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);
echo $jsonOutput; Spiegazione
Il codice parte da un JSON che rappresenta un ordine e lo trasforma in una struttura PHP associativa. Il primo passaggio importante è questo:
$data = json_decode($jsonInput, true, 512, JSON_THROW_ON_ERROR); Il parametro true dice a PHP di convertire il JSON in array associativi invece che in oggetti. Questa scelta è spesso più comoda quando si devono gestire livelli annidati in modo dinamico. L’opzione JSON_THROW_ON_ERROR è fondamentale perché evita di ignorare errori di parsing: se il JSON è rotto, PHP lancerà un’eccezione.
Subito dopo estraiamo i blocchi principali con l’operatore di coalescenza null ??. Questo approccio è molto utile perché evita accessi diretti a chiavi inesistenti:
$cliente = $ordine[´cliente´] ?? []; In questo modo, anche se la chiave cliente non esiste, il codice non si interrompe immediatamente. Naturalmente, questo non sostituisce la validazione: serve solo a rendere l’accesso più robusto.
La validazione minima controlla i dati obbligatori, come nome ed email. Per l’email usiamo filter_var() con FILTER_VALIDATE_EMAIL, una soluzione semplice e affidabile per verifiche di base.
La parte più interessante è il ciclo sugli articoli. Ogni articolo è un array annidato dentro articoli, quindi il ciclo deve verificare che ogni elemento sia davvero un array. Per ciascun prodotto leggiamo SKU, nome, quantità e prezzo. Se quantità o prezzo non sono validi, l’elemento viene scartato.
Questo pattern è molto utile in scenari reali: i dati JSON ricevuti da frontend o servizi esterni possono essere parzialmente incompleti, e il tuo codice deve saperli filtrare senza andare in errore.
Infine costruiamo un nuovo array $output più pulito e coerente, adatto a essere mostrato a schermo, salvato in database o inviato a un altro servizio. La ricodifica finale con json_encode() usa:
- JSON_PRETTY_PRINT per rendere il risultato leggibile
- JSON_UNESCAPED_UNICODE per mantenere i caratteri accentati correttamente
- JSON_THROW_ON_ERROR per intercettare eventuali problemi di serializzazione
Best practice
Gestire JSON annidati in PHP richiede alcune abitudini tecniche che fanno davvero la differenza nei progetti reali.
- Usa sempre json_decode() con controllo errori: meglio lanciare eccezioni che lavorare con dati corrotti senza accorgersene.
- Preferisci accessi difensivi: usa ??, is_array() e controlli espliciti prima di leggere chiavi profonde.
- Valida i dati subito dopo la decodifica: non rimandare i controlli troppo avanti nel flusso.
- Normalizza i dati: se il JSON arriva da fonti diverse, trasformalo in una struttura coerente prima di usarlo nel resto dell’applicazione.
- Evita catene di accesso troppo lunghe: invece di scrivere percorsi complessi ovunque, assegna blocchi intermedi a variabili come $cliente o $indirizzo.
- Separa parsing e logica di business: prima leggi e valida il JSON, poi esegui calcoli o operazioni applicative.
- Gestisci i numeri con attenzione: quantità e prezzi devono essere convertiti esplicitamente in int o float.
Un altro consiglio importante è non fidarsi mai della struttura ricevuta. Anche se un JSON è corretto dal punto di vista sintattico, potrebbe non essere corretto dal punto di vista semantico. Ad esempio, la chiave articoli potrebbe contenere un array vuoto, oppure un valore stringa al posto di un elenco. Il controllo del tipo è quindi essenziale.
Riepilogo
La gestione di array annidati e strutture complesse in JSON è una competenza molto utile in PHP, soprattutto quando si lavora con API, form avanzati e dati provenienti da sistemi esterni. In questo tutorial hai visto come:
- decodificare JSON in modo sicuro con json_decode() e JSON_THROW_ON_ERROR;
- accedere a strutture annidate senza generare errori;
- validare campi obbligatori e tipi di dato;
- elaborare array complessi come liste di articoli;
- ricostruire un JSON pulito e leggibile con json_encode().
Il punto chiave è questo: non limitarti a leggere il JSON, ma trasformalo in una struttura affidabile per il tuo codice. Più il JSON è annidato, più è importante adottare un approccio graduale, con controlli intermedi e dati normalizzati.
Approfondisci con risorse ufficiali
- PHP Manual - json_decode(): documentazione ufficiale sulla decodifica JSON.
- PHP Manual - json_encode(): opzioni e comportamento della serializzazione.
- PHP Manual - JSON constants: elenco completo delle costanti come JSON_THROW_ON_ERROR e JSON_PRETTY_PRINT.
- PHP Manual - filter_var(): utile per validare email, URL e altri valori.
- PHP Manual - is_array() e funzioni di controllo tipo: fondamentali per lavorare con strutture annidate in sicurezza.
