Menu

JSON in Python: leggere, scrivere e fare il parsing con il modulo json

Come leggere e scrivere JSON in Python: loads, dumps, lettura da file, pretty printing e i casi limite che saltano fuori con i dati reali.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

JSON e Python parlano la stessa lingua

JSON è il formato standard per API, file di configurazione e scambio di dati sul web. Per fortuna di chi programma in Python, un oggetto JSON corrisponde direttamente a un dict Python, un array JSON a una lista, una stringa JSON a uno str. È proprio questa corrispondenza a rendere la lettura e la scrittura di JSON in Python un'operazione da due righe.

Il modulo json della libreria standard gestisce entrambe le direzioni.

Fare il parsing di una stringa JSON

json.loads(text), cioè "load string", riceve una stringa in formato JSON e restituisce l'oggetto Python che rappresenta:

Il risultato è un normale dict. Accedi alle sue chiavi come con qualsiasi dict: nessun wrapper JSON speciale, nessun metodo .parse() sul risultato.

Se la stringa non è JSON valido, json.loads solleva json.JSONDecodeError. Il messaggio di errore indica la riga e la colonna del problema, e di solito basta per individuare una virgola mancante o un apice non escapato.

Scrivere JSON come stringa

json.dumps(data), cioè "dump string", fa l'opposto: riceve un oggetto Python e restituisce una stringa JSON:

True, False e None di Python vengono tradotti automaticamente in true, false e null di JSON. Numeri e stringhe passano invariati. Le liste diventano array, i dict diventano oggetti.

Pretty printing

L'output predefinito di json.dumps è compatto: va benissimo per la trasmissione in rete, meno per gli occhi umani. Passa indent=2 per ottenere qualcosa di più leggibile:

Altre opzioni di dumps che vale la pena conoscere:

  • sort_keys=True: ordina alfabeticamente le chiavi degli oggetti. Utile per avere un output deterministico (file di configurazione, fixture di test, diff).
  • ensure_ascii=False: scrive i caratteri non ASCII (é, ü, 中) così come sono, invece che come escape \u. Di solito è la scelta giusta per i file UTF-8.
  • separators=(",", ":"): l'output più compatto possibile. Insieme a ensure_ascii=False produce il JSON UTF-8 più compatto che puoi ottenere.

Leggere JSON da un file

json.load(file), senza la s, legge direttamente da un oggetto file. Lo schema tipico lo abbina a with open:

import json

with open("config.json") as f:
    config = json.load(f)

print(config["version"])

Non serve leggere prima tutto il file in una stringa: json.load lavora direttamente sull'oggetto file.

Scrivere JSON su un file

json.dump(data, file) è la controparte per la scrittura su file:

import json

data = {"created": "2026-01-01", "items": [1, 2, 3]}

with open("state.json", "w") as f:
    json.dump(data, f, indent=2)

Anche qui funziona l'opzione indent. Apri il file generato e troverai un documento JSON ben formattato.

Leggere la risposta JSON di un'API

La maggior parte delle librerie HTTP ti restituisce byte o testo; chiami json.loads per trasformarli in dati utilizzabili:

import json
import urllib.request

with urllib.request.urlopen("https://api.example.com/users/1") as response:
    text = response.read().decode("utf-8")

user = json.loads(text)
print(user["name"])

La libreria requests (trattata a parte) ti fa saltare un passaggio: la risposta ha un metodo .json() che chiama json.loads al posto tuo.

Cosa JSON può e non può rappresentare

Il sistema di tipi di JSON è più limitato di quello di Python. La corrispondenza nelle due direzioni:

PythonJSON
dictoggetto
list, tuplearray
strstringa
int, floatnumero
Truetrue
Falsefalse
Nonenull

Le tuple tornano indietro come liste: la natura di tupla si perde. Set, classi personalizzate e oggetti datetime non si possono serializzare di default; ottieni TypeError: Object of type X is not JSON serializable.

Gestire datetime e oggetti personalizzati

Ci sono due approcci comuni.

Converti prima in una struttura compatibile con JSON. Fai la trasformazione nel tuo codice, poi serializza un semplice dict:

Passa una funzione default=. json.dumps la chiama per ogni valore che non sa come serializzare:

Quando rileggi i dati, devi riconvertire tu quelle stringhe ISO in datetime: JSON non ricorda cosa fossero in origine.

Andata e ritorno di un dict attraverso JSON

Un rapido controllo che i dict sopravvivono al viaggio:

I valori sono uguali, ma sono oggetti diversi. Spesso è proprio quello che vuoi: json.dumps + json.loads è un modo economico per fare una copia profonda di qualsiasi struttura compatibile con JSON.

Un esempio realistico

Un piccolo script che carica una configurazione JSON, aggiorna un campo e la salva di nuovo:

import json
from pathlib import Path

config_path = Path("settings.json")

# Carica (con un valore predefinito se il file non esiste).
if config_path.exists():
    config = json.loads(config_path.read_text())
else:
    config = {"theme": "dark", "last_opened": None}

# Aggiorna.
config["last_opened"] = "2026-01-15"

# Salva, con pretty print.
config_path.write_text(json.dumps(config, indent=2, ensure_ascii=False))

Ecco un ciclo completo "leggi, modifica, scrivi" in una dozzina di righe.

Qualche buona abitudine

  • Usa sempre with open(...) per i file. JSON è solo testo: valgono tutte le regole sulla gestione dei file.
  • Preferisci indent=2 per i file letti da persone: configurazioni, fixture, dati esportati. Evitalo per il traffico di rete, dove conta la compattezza.
  • Imposta ensure_ascii=False per l'output UTF-8, così i nomi con accenti o caratteri non latini restano leggibili.
  • Valida con try/except json.JSONDecodeError quando fai il parsing di dati che non hai prodotto tu.

Prossimo argomento

JSON gestisce dati chiave-valore. Il prossimo strumento dello stesso capitolo è CSV: il supporto integrato di Python per il formato tabellare che sta dietro alla maggior parte delle esportazioni da foglio di calcolo che incontrerai.

Domande frequenti

Come faccio il parsing di JSON in Python?

Usa json.loads(text) per una stringa JSON oppure json.load(file) per un oggetto file. Entrambi restituiscono un dict Python (o una lista, a seconda del JSON). Esempio: data = json.loads('{"name": "Rosa"}'), e a quel punto data['name'] vale 'Rosa'.

Come converto un dizionario Python in JSON?

json.dumps(my_dict) restituisce una stringa JSON. json.dump(my_dict, file) scrive direttamente su un oggetto file. Passa indent=2 per un output formattato: json.dumps(data, indent=2).

Che differenza c'è tra json.loads e json.load?

loads (con la s) riceve una stringa. load (senza s) riceve un oggetto file. Lo stesso vale per dumps e dump. La s sta per string: è il modo più semplice per ricordare quale è quale.

Come gestisco date e oggetti personalizzati in JSON?

JSON non ha un tipo data, quindi passa le date come stringhe ISO-8601 e riconvertile a mano quando le rileggi. Per le classi personalizzate, puoi fornire a json.dumps una funzione default= che restituisca una rappresentazione compatibile con JSON, oppure convertire tu stesso l'oggetto in un dict prima di serializzarlo.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA