JSON Formatter Python — Guida a json.dumps()
Usa il Formattatore e Abbellitore JSON gratuito direttamente nel tuo browser — nessuna installazione.
Prova Formattatore e Abbellitore JSON online →Quando sto eseguendo il debug di un client API Python, la prima cosa a cui ricorro è python formattare json — una singola chiamata a json.dumps(data, indent=4) e un blob illeggibile su una sola riga diventa immediatamente navigabile. Il modulo integrato json di Python gestisce tutto ciò interamente nella libreria standard — nessuna installazione di terze parti richiesta. Se hai solo bisogno di un risultato rapido senza scrivere codice, il Formattatore JSON di ToolDeck lo fa istantaneamente. Questa guida copre ogni metodo pratico: json.dumps() con tutti i suoi parametri, pprint, orjson per la formattazione ad alte prestazioni, la CLI json.tool, e scenari reali come la formattazione delle risposte API e la lettura da disco — tutto con codice compatibile con Python 3.8+. Copre anche la serializzazione di tipi personalizzati come datetime e UUID, lo streaming di file da gigabyte con ijson, e la colorazione sintattica nel terminale con rich.
- →
json.dumps(data, indent=4)è integrato nella stdlib di Python dalla versione 2.6 — nessuna installazione necessaria. - →Passa
ensure_ascii=Falseogni volta che i tuoi dati contengono lettere accentate, caratteri CJK o emoji. - →Per
datetime,UUIDo classi personalizzate usa il parametrodefault=o crea una sottoclasse dijson.JSONEncoder. - →
separators=(',', ':')elimina tutti gli spazi — da usare per la trasmissione in rete o l'incorporamento negli URL. - →
orjsonè 5–10× più veloce della stdlib e gestisce nativamentedatetimeeuuid.UUID. - →
pprint.pprint()produce sintassi Python (True/None), non JSON valido — non usare mai per file o risposte API. - →Per file JSON superiori a 50 MB, fai lo streaming con
ijsoninvece dijson.load()per evitareMemoryError.
Cos'è la formattazione JSON leggibile?
La formattazione leggibile (pretty printing) trasforma una stringa JSON densa e minificata in un formato leggibile dall'uomo con indentazione coerente e interruzioni di riga. La trasformazione è puramente cosmetica: i dati sono identici, cambia solo la presentazione. Il modulo json di Python gestisce tutto ciò interamente nella libreria standard — niente da installare.
{"id":"usr_9f3a2b","name":"Marco Rossi","roles":["admin","editor"],"prefs":{"theme":"dark","lang":"it"}}{
"id": "usr_9f3a2b",
"name": "Marco Rossi",
"roles": [
"admin",
"editor"
],
"prefs": {
"theme": "dark",
"lang": "it"
}
}json.dumps() — Il metodo standard per formattare JSON
json.dumps() fa parte della libreria standard di Python dalla versione 2.6 — semplicemente import json, nessuna installazione necessaria. Serializza qualsiasi oggetto Python compatibile con JSON in una stringa formattata. Il parametro chiave è indent: impostalo a 4 (o 2) per ottenere un output leggibile.
import json
utente = {
"id": "usr_9f3a2b",
"name": "Marco Rossi",
"roles": ["admin", "editor"],
"prefs": {"theme": "dark", "lang": "it"}
}
print(json.dumps(utente, indent=4, ensure_ascii=False))
# Output:
# {
# "id": "usr_9f3a2b",
# "name": "Marco Rossi",
# "roles": [
# "admin",
# "editor"
# ],
# "prefs": {
# "theme": "dark",
# "lang": "it"
# }
# }Per uso in produzione vorrai spesso sort_keys=True (output coerente tra le esecuzioni) e ensure_ascii=False (mantenere i caratteri non-ASCII leggibili):
import json
risposta_api = {
"timestamp": "2024-05-01T10:30:00Z",
"status": "success",
"data": {
"user_id": "usr_9f3a2b",
"display_name": "Giulia Ferrari",
"citta": "Milano",
"score": 4892.5,
"tags": ["python", "backend", "api"]
}
}
print(json.dumps(risposta_api, indent=4, sort_keys=True, ensure_ascii=False))
# Output (chiavi ordinate, accenti preservati):
# {
# "data": {
# "citta": "Milano",
# "display_name": "Giulia Ferrari",
# "score": 4892.5,
# "tags": ["api", "backend", "python"],
# "user_id": "usr_9f3a2b"
# },
# "status": "success",
# "timestamp": "2024-05-01T10:30:00Z"
# }json.dumps() restituisce una stringa. Per scrivere JSON formattato direttamente in un file, usa json.dump(data, f, indent=4) (senza la s) — scrive in un oggetto file ed evita di creare una stringa intermedia in memoria.Riferimento dei parametri di json.dumps()
Tutti i parametri sono opzionali tranne l'oggetto stesso. I valori di default producono JSON compatto e sicuro in ASCII — passa i parametri esplicitamente per un output leggibile dall'uomo.
Output JSON compatto con il parametro separators
Per default json.dumps() separa gli elementi con ", " e le chiavi dai valori con ": ". Il parametro separators sovrascrive entrambi. Passare (',', ':') elimina tutti gli spazi per produrre il JSON valido più compatto possibile — utile per la trasmissione in rete, l'incorporamento negli URL o la memorizzazione di JSON in una colonna di database dove ogni byte conta.
import json
payload = {
"endpoint": "/api/v2/events",
"filters": {"status": "active", "limit": 100},
"sort": "desc"
}
# Default — spazi dopo i separatori (leggibile)
output_normale = json.dumps(payload)
# {"endpoint": "/api/v2/events", "filters": {"status": "active", "limit": 100}, "sort": "desc"}
# len = 88
# Compatto — nessuno spazio
output_compatto = json.dumps(payload, separators=(',', ':'))
# {"endpoint":"/api/v2/events","filters":{"status":"active","limit":100},"sort":"desc"}
# len = 80 (9% più piccolo; il risparmio cresce con payload più grandi e profondamente annidati)
# Compatto + chiavi ordinate per chiavi di cache riproducibili o hash di contenuto
canonico = json.dumps(payload, separators=(',', ':'), sort_keys=True)
print(canonico)
# {"endpoint":"/api/v2/events","filters":{"limit":100,"status":"active"},"sort":"desc"}indent= insieme a separators=, l'argomento separators controlla solo i separatori inline — le interruzioni di riga e l'indentazione di indent vengono preservate. Per un output compatto su una sola riga, ometti indent (o passa None) e imposta separators=(',', ':').Serializzare oggetti Python personalizzati con il parametro default
Il modulo standard json serializza dict, liste, stringhe, numeri, booleani e None — ma solleva un TypeError per qualsiasi altro tipo. I due colpevoli più comuni nel codice di produzione sono gli oggetti datetime e gli UUID.
import json
from datetime import datetime, timezone
import uuid
ordine = {
"order_id": uuid.uuid4(), # ❌ TypeError: UUID is not JSON serializable
"placed_at": datetime.now(timezone.utc), # ❌ TypeError: datetime is not JSON serializable
"totale_eur": 142.50,
"items": ["pro-subscription", "addon-storage"]
}
json.dumps(ordine) # solleva TypeErrorApproccio 1 — il parametro default=
Passa un callable a default=. json.dumps() lo chiama per qualsiasi oggetto che non riesce a gestire. Restituisci una rappresentazione serializzabile, oppure solleva TypeError per i tipi che non supporti esplicitamente — non ignorare mai silenziosamente i tipi sconosciuti.
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal
def json_default(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"Type {type(obj).__name__!r} is not JSON serializable")
ordine = {
"order_id": uuid.uuid4(),
"placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"totale_eur": Decimal("142.50"),
"items": ["pro-subscription", "addon-storage"]
}
print(json.dumps(ordine, indent=4, default=json_default))
# {
# "order_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "placed_at": "2024-05-01T10:30:00+00:00",
# "totale_eur": 142.5,
# "items": ["pro-subscription", "addon-storage"]
# }Approccio 2 — sottoclasse di json.JSONEncoder
Per la logica di codifica riutilizzabile condivisa tra più moduli, creare una sottoclasse di json.JSONEncoder è più pulito che passare una funzione default ovunque. Sovrascrivi il metodo default e chiama super().default(obj) come ultimo fallback — questo preserva il corretto comportamento di errore per i tipi non supportati.
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal
class AppEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
return super().default(obj) # solleva TypeError per i tipi sconosciuti
ordine = {
"order_id": uuid.uuid4(),
"placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"totale_eur": Decimal("142.50"),
}
# Passa la classe encoder tramite cls=
print(json.dumps(ordine, indent=4, cls=AppEncoder))
# Output identico all'approccio con default=super().default(obj) (o solleva TypeError esplicitamente) per i tipi non riconosciuti. Restituire silenziosamente str(obj) per tutto corromperà gli oggetti che avrebbero dovuto sollevare un errore — un bug difficile da rintracciare in produzione.Decodifica inversa — object_hook
La codifica è solo metà della storia. Per ricostruire un oggetto Python personalizzato dal JSON, passa una funzione object_hook a json.loads() o json.load(). L'hook viene chiamato per ogni oggetto JSON decodificato (dict) e può restituire qualsiasi valore Python — fornendoti un ciclo completo di codifica ↔ decodifica.
import json
from datetime import datetime
from dataclasses import dataclass
@dataclass
class Event:
name: str
occurred_at: datetime
user_id: str
def encode_event(obj):
if isinstance(obj, Event):
return {
"__type__": "Event",
"name": obj.name,
"occurred_at": obj.occurred_at.isoformat(),
"user_id": obj.user_id,
}
raise TypeError(f"Cannot serialize {type(obj)}")
def decode_event(d):
if d.get("__type__") == "Event":
return Event(
name=d["name"],
occurred_at=datetime.fromisoformat(d["occurred_at"]),
user_id=d["user_id"],
)
return d
# Codifica
event = Event("login", datetime(2024, 5, 1, 10, 30), "usr_9f3a2b")
json_str = json.dumps(event, default=encode_event, indent=4)
# Decodifica in un'istanza Event
restored = json.loads(json_str, object_hook=decode_event)
print(type(restored)) # <class 'Event'>
print(restored.occurred_at) # 2024-05-01 10:30:00object_hook viene chiamato per ogni dict annidato nel documento — non solo al livello superiore. Includi un campo discriminatore (come "__type__") in modo che l'hook possa distinguere i tuoi oggetti personalizzati dai dict semplici che devono rimanere tali.pprint — Il modulo alternativo (e quando non usarlo)
Il modulo pprint di Python (pretty printer) formatta le strutture dati Python per la leggibilità nel terminale. Funziona su oggetti Python analizzati, non su stringhe JSON — e il suo output usa la sintassi Python, non la sintassi JSON.
import json, pprint
raw = '{"sensor_id":"s-441","readings":[23.1,23.4,22.9],"unit":"celsius","active":true}'
data = json.loads(raw)
# pprint — repr Python valido, NON JSON valido
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
# 'readings': [23.1, 23.4, 22.9],
# 'unit': 'celsius',
# 'active': True} ← Python True, non JSON true
# json.dumps — JSON valido
print(json.dumps(data, indent=4))
# {
# "sensor_id": "s-441",
# "readings": [23.1, 23.4, 22.9],
# "unit": "celsius",
# "active": true ← JSON valido
# }pprint a un endpoint API o scriverlo in un file .json — farà fallire qualsiasi parser JSON che si aspetti la sintassi standard. Usa json.dumps(indent=4) per qualsiasi output che deve essere JSON valido.Quando pprint ha senso: ispezione rapida nel REPL o nel log di debug, specialmente quando l'oggetto contiene tipi non serializzabili in JSON (set, istanze di classi personalizzate, dataclass prima della conversione).
Come formattare una risposta JSON da Requests
Lo scenario reale più comune: hai un file JSON su disco o una risposta HTTP da un'API, e vuoi formattarlo per il debug o il logging. Entrambi i casi usano lo stesso approccio — analizza in un dict Python, poi formatta con json.dumps().
Lettura da un file
import json
try:
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
# Stampa nella console
print(json.dumps(data, indent=4, ensure_ascii=False))
# Oppure scrivi la versione formattata su disco
with open("config.formattato.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"JSON non valido: {e}")
except FileNotFoundError:
print(f"File non trovato: config.json")Formattazione di una risposta API
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout
def stampa_api(url: str) -> None:
try:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
except HTTPError as e:
print(f"HTTP {e.response.status_code}: {e}")
except (ConnectionError, Timeout) as e:
print(f"Errore di rete: {e}")
except json.JSONDecodeError:
print(f"Il corpo della risposta non è JSON:\n{resp.text[:500]}")
stampa_api("https://api.github.com/repos/python/cpython")response.json() analizza già il corpo della risposta — non è necessario chiamare json.loads() separatamente. Aggiungi sempre raise_for_status() prima di accedere a .json() per intercettare gli errori 4xx/5xx prima che causino un confuso errore di parsing.Formattazione da riga di comando
Python viene fornito con json.tool, un modulo CLI per formattare JSON direttamente dal terminale — nessuno script Python necessario. Disponibile su qualsiasi macchina con Python installato.
# Formattare un file locale
python -m json.tool config.json
# Inviare la risposta API attraverso il formattatore
curl -s https://api.github.com/users/gvanrossum | python -m json.tool
# Formattare da stdin
echo '{"service":"api-gateway","version":"2.1.0","healthy":true}' | python -m json.tool
# Ordinare le chiavi alfabeticamente
python -m json.tool --sort-keys data.json
# Indentazione personalizzata (Python 3.9+)
python -m json.tool --indent 2 data.json--indent e --no-indent. Per un filtraggio JSON più potente nel terminale, considera jq — ma python -m json.toolcopre il caso d'uso della formattazione senza dipendenze aggiuntive.Se non sei affatto nel terminale — incollando una risposta Postman o un file di log — il Formattatore JSON di ToolDeck ti permette di incollare, formattare e copiare in un solo passaggio con evidenziazione della sintassi e validazione integrate.
Librerie alternative: orjson e rich
orjson — 5–10× più veloce con supporto nativo dei tipi
Il modulo standard json è abbastanza veloce per la maggior parte dei casi, ma se stai serializzando migliaia di oggetti al secondo — pipeline di logging, API ad alto throughput, grandi esportazioni di dati — orjson è 5–10× più veloce. Gestisce anche nativamente tipi che la libreria standard non riesce a serializzare senza una funzione default personalizzata: datetime, uuid.UUID, array numpy e dataclass.
pip install orjson
import orjson
from datetime import datetime, timezone
import uuid
event = {
"event_id": uuid.uuid4(), # nessun str() necessario — orjson gestisce UUID
"timestamp": datetime.now(timezone.utc), # nessun isoformat() necessario
"service": "auth-service",
"level": "INFO",
"payload": {
"user_id": "usr_9f3a2b",
"action": "login",
"ip": "192.168.1.42",
"latency_ms": 34
}
}
# orjson.dumps restituisce bytes; .decode() converte in str
print(orjson.dumps(event, option=orjson.OPT_INDENT_2).decode())
# {
# "event_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "timestamp": "2024-05-01T10:30:00+00:00",
# "service": "auth-service",
# ...
# }Due cose da sapere: orjson.dumps() restituisce bytes, non una stringa — chiama .decode() se hai bisogno di una stringa. Supporta solo l'indentazione a 2 spazi tramite OPT_INDENT_2; per output a 4 spazi usa il standard json.dumps(indent=4).
rich — Colorazione sintattica nel terminale
Se ispezioni regolarmente JSON in un terminale o REPL, rich visualizza output con codice colore e colorazione sintattica che rende le strutture profondamente annidate leggibili a colpo d'occhio. Chiavi, stringhe, numeri e booleani hanno ciascuno un colore distinto — molto più facile da analizzare di un muro di testo monocromatico. È uno strumento solo per il debug, non per la serializzazione in produzione.
pip install rich
from rich import print_json
import json
# print_json() accetta una stringa JSON
raw = '{"event":"login","user_id":"usr_9f3a2b","timestamp":"2024-05-01T10:30:00Z","success":true,"meta":{"ip":"192.168.1.42","attempts":1}}'
print_json(raw)
# Per formattare un dict Python, convertilo prima in stringa
data = {
"status": "success",
"count": 42,
"tags": ["python", "api", "backend"]
}
print_json(json.dumps(data))rich.print_json() emette codici di escape ANSI per il colore del terminale — non catturare mai questo output e scriverlo in un file .json o inviarlo come risposta API. Usa json.dumps(indent=4) per qualsiasi output leggibile dalla macchina.simplejson — Sostituto compatibile con la stdlib
simplejson è la libreria che è diventata il modulo standard json di Python — è ancora mantenuta indipendentemente e rimane avanti rispetto alla stdlib su funzionalità minori. È un vero sostituto drop-in: cambia l'import e il resto del codice rimane invariato. Utile quando hai bisogno del supporto Decimal senza un encoder personalizzato, o quando hai ambienti Python più vecchi.
pip install simplejson
import simplejson as json # API identica alla stdlib
from decimal import Decimal
ordine = {
"item": "Abbonamento API Roma",
"price": Decimal("49.99"), # stdlib json solleverebbe TypeError qui
"quantity": 3,
}
# simplejson serializza Decimal nativamente — nessun default= necessario
print(json.dumps(ordine, indent=4, use_decimal=True))
# {
# "item": "Abbonamento API Roma",
# "price": 49.99,
# "quantity": 3
# }orjson è la scelta migliore. Usa simplejson quando hai bisogno della serializzazione nativa di Decimal senza scrivere un encoder personalizzato, o quando mantieni una codebase che lo usa già.Elaborazione di file JSON di grandi dimensioni senza esaurire la memoria
json.load() legge l'intero file in memoria prima di poter accedere a un singolo campo. Su un file con milioni di record o un payload superiore a un gigabyte, questo causa un MemoryError — o nel migliore dei casi forza il processo a fare swap su disco e procedere molto lentamente.
Streaming con ijson
ijsonè un parser JSON in streaming che genera elementi uno alla volta da un oggetto file. Iteri sugli elementi dell'array senza mai tenere l'intero dataset in memoria — il picco di memoria rimane proporzionale a un singolo oggetto, non alla dimensione del file.
pip install ijson
import ijson
from decimal import Decimal
# events.json struttura: {"events": [...milioni di oggetti...]}
ricavo_totale = Decimal("0")
contatore_login = 0
with open("events.json", "rb") as f: # ijson richiede la modalità binaria
for event in ijson.items(f, "events.item"):
if event.get("type") == "purchase":
ricavo_totale += Decimal(str(event["amount_eur"]))
elif event.get("type") == "login":
contatore_login += 1
print(f"Ricavo: {ricavo_totale:.2f} EUR | Login: {contatore_login}")
# Elabora un file da 2 GB con ~30 MB di picco di utilizzo della memoriajson.load() a ijson quando il tuo file supera circa 50–100 MB. Al di sotto di quella soglia json.load() è più semplice e significativamente più veloce perché usa internamente un parser con estensione C. Al di sopra di 100 MB, il risparmio di memoria dallo streaming supera il costo aggiuntivo.NDJSON — un oggetto JSON per riga
NDJSON (Newline Delimited JSON, anche chiamato JSON Lines o .jsonl) memorizza un oggetto JSON completo per riga. Gli esportatori di log, i consumer Kafka e le pipeline di dati producono frequentemente questo formato perché ogni riga può essere aggiunta e letta in modo indipendente. La libreria standard lo gestisce senza dipendenze aggiuntive.
import json
from pathlib import Path
# Scrivere NDJSON — un evento per riga
events = [
{"ts": "2024-05-01T10:00:00Z", "user": "usr_9f3a2b", "action": "login"},
{"ts": "2024-05-01T10:01:03Z", "user": "usr_9f3a2b", "action": "purchase", "sku": "pro-plan"},
{"ts": "2024-05-01T10:15:42Z", "user": "usr_4ab1d9", "action": "login"},
]
with open("events.ndjson", "w", encoding="utf-8") as f:
for event in events:
f.write(json.dumps(event, ensure_ascii=False) + "\n")
# Leggere NDJSON — memoria costante, indipendentemente dalla dimensione del file
contatore_acquisti = 0
with open("events.ndjson", "r", encoding="utf-8") as f:
for riga in f:
riga = riga.strip()
if not riga: # salta le righe vuote
continue
event = json.loads(riga)
if event.get("action") == "purchase":
contatore_acquisti += 1
print(f"{event['ts']} — {event['user']} ha acquistato {event['sku']}")Errori Comuni
Ho visto questi quattro errori in quasi ogni code review che riguarda la serializzazione JSON — specialmente da sviluppatori che arrivano da JavaScript dove JSON.stringify gestisce la codifica automaticamente.
Problema: print() su un dict usa il repr Python — l'output mostra True/None (sintassi Python), non true/null (sintassi JSON). Non è JSON valido.
Soluzione: Usa sempre json.dumps(data, indent=4) per un output JSON valido e leggibile.
data = {"active": True, "count": None}
print(data)
# {'active': True, 'count': None}print(json.dumps(data, indent=4))
# {
# "active": true,
# "count": null
# }Problema: I caratteri speciali (lettere accentate, CJK, emoji) vengono trasformati in sequenze \\uXXXX, rendendo l'output illeggibile.
Soluzione: Passa ensure_ascii=False per preservare i caratteri Unicode originali.
user = {"name": "Giulia Ferrari", "citta": "città"}
json.dumps(user, indent=2)
# {"name": "Giulia Ferrari", "citta": "citt\u00e0"}json.dumps(user, indent=2, ensure_ascii=False)
# {"name": "Giulia Ferrari", "citta": "città"}Problema: json.dumps() restituisce una stringa; poi hai bisogno di una chiamata f.write() separata, creando una stringa intermedia non necessaria.
Soluzione: Usa json.dump(data, f, indent=4) — scrive direttamente nell'oggetto file.
with open("out.json", "w") as f:
f.write(json.dumps(data, indent=4))with open("out.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)Problema: pprint.pprint() usa la sintassi Python (True, None, virgolette singole) che i parser JSON rifiutano.
Soluzione: Usa json.dumps(indent=4) per qualsiasi output che deve essere analizzabile come JSON.
import pprint
pprint.pprint({"running": True, "last_error": None})
# {'running': True, 'last_error': None}import json
print(json.dumps({"running": True, "last_error": None}, indent=4))
# {"running": true, "last_error": null}Confronto dei metodi — json.dumps, orjson, simplejson, rich
Usa json.dumps() per la formattazione quotidiana e la scrittura di file — copre il 95% dei casi senza dipendenze. Ricorri a orjson quando serializzi in un percorso critico o quando i tuoi oggetti includono campi datetime e UUID. Usa simplejson quando hai bisogno di compatibilità drop-in con la stdlib e supporto Decimal pronto all'uso. Riserva rich.print_json() e pprint strettamente per l'ispezione locale nel terminale — nessuno dei due produce output leggibile dalla macchina.
Domande Frequenti
Come si visualizza il JSON in modo leggibile in Python?
Chiama json.dumps(data, indent=4). Il parametro indent imposta il numero di spazi per livello di annidamento. Importa prima il modulo json — è incluso nella libreria standard di Python, nessun pip install necessario. Passa ensure_ascii=False se i tuoi dati contengono lettere accentate, caratteri CJK o emoji.
import json
utente = {"username": "mrossi", "piano": "enterprise", "permessi": ["lettura", "scrittura", "deploy"]}
print(json.dumps(utente, indent=4, ensure_ascii=False))Qual è la differenza tra json.dumps() e json.dump()?
json.dumps() (con la "s") restituisce una stringa formattata in memoria. json.dump() (senza "s") scrive direttamente in un oggetto file — passa l'handle del file aperto come secondo argomento. Per scrivere JSON formattato su disco, json.dump(data, f, indent=4) è idiomatico e evita di creare una stringa intermedia.
# dumps → stringa in memoria
formattato = json.dumps(data, indent=4)
# dump → scrittura diretta nel file
with open('output.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)Perché json.dumps() mostra \u00e0\u00e8\u00ec invece dei caratteri reali?
Per default ensure_ascii=True fa l'escape di ogni carattere non-ASCII in una sequenza \uXXXX. Imposta ensure_ascii=False per preservare i caratteri Unicode originali. Questo è particolarmente importante per nomi, indirizzi e qualsiasi contenuto generato dagli utenti in italiano o altre lingue non latine.
data = {"citta": "città", "bevanda": "perché", "parola": "è"}
# Default — con escape
json.dumps(data, indent=4)
# {"citta": "citt\u00e0", "bevanda": "perch\u00e9", ...}
# Leggibile
json.dumps(data, indent=4, ensure_ascii=False)
# {"citta": "città", "bevanda": "perché", "parola": "è"}Come si formatta una stringa JSON (non un dict)?
Prima analizza la stringa con json.loads(), poi formatta con json.dumps(). Le due chiamate possono essere concatenate in una riga per un'ispezione rapida nel terminale.
import json
raw = '{"endpoint":"/api/v2/utenti","timeout":30,"riprova":true}'
print(json.dumps(json.loads(raw), indent=4))Posso usare pprint per formattare JSON in Python?
pprint.pprint() produce una rappresentazione degli oggetti Python, non JSON valido. Usa True/False/None (sintassi Python) invece di true/false/null (sintassi JSON). Non passare mai l'output di pprint a un'API o un parser JSON — usa json.dumps(indent=4) per tutto ciò che deve essere JSON valido.
import pprint, json
data = {"attivo": True, "punteggio": None}
pprint.pprint(data) # {'attivo': True, 'punteggio': None} ← non è JSON
json.dumps(data, indent=4) # {"attivo": true, "punteggio": null} ← JSON validoCome si ordinano le chiavi JSON alfabeticamente in Python?
Aggiungi sort_keys=True a json.dumps(). Da riga di comando, usa python -m json.tool --sort-keys data.json. Le chiavi ordinate rendono i diff JSON leggibili e aiutano a individuare i valori cambiati a colpo d'occhio.
import json
server = {"workers": 4, "host": "0.0.0.0", "port": 8080, "debug": False}
print(json.dumps(server, indent=4, sort_keys=True))
# {
# "debug": false,
# "host": "0.0.0.0",
# "port": 8080,
# "workers": 4
# }Python ti dà pieno controllo — serializzatori personalizzati, streaming, integrazione pipeline. Quando hai solo bisogno di ispezionare o condividere uno snippet formattato, il Formattatore JSON di ToolDeck è il percorso più veloce: incolla il tuo JSON e ottieni un risultato indentato ed evidenziato senza configurare alcun ambiente.
Strumenti Correlati
Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.
Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.