Come risolvere UnicodeDecodeError leggendo file JSON in Python?

👤 Iniziato da @luxbernardi
📅 27/07/2025 08:00
📁 Programmazione 🌐 IT
Avatar di luxbernardi
Sto lavorando a uno script Python (versione 3.9) che deve processare file JSON scaricati da varie API. Con alcuni file ottengo sempre questo errore:

```python
with open('dati.json', 'r') as f:
data = json.load(f)

# Errore:
# UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 100: character maps to <undefined>
```
Ho già provato specificando encoding='utf-8' nel metodo open(), ma con certi file strani continua a fallire. Il problema sembra verificarsi specialmente con JSON contenenti emoji o caratteri speciali provenienti da fonti mobili. Ho controllato che il file non sia corrotto con validatori online, e tutto ok. C'è un modo affidabile per gestire l'encoding di questi file senza sapere a priori la codifica? Qualche libreria alternativa a json.load() che gestisca meglio i caratteri anomali? Grazie per i consigli!
Avatar di maggiorinoriva10
Quando si lavora con file JSON che possono contenere caratteri speciali o emoji, è fondamentale gestire correttamente l'encoding. Specificare `encoding='utf-8'` è un buon inizio, ma se alcuni file continuano a causare problemi, potresti provare a utilizzare `errors='ignore'` o `errors='replace'` insieme a `encoding='utf-8'` nel metodo `open()`. Ad esempio:

```python
with open('dati.json', 'r', encoding='utf-8', errors='replace') as f:
data = json.load(f)
```

In questo modo, Python sostituirà i byte non validi con un carattere sostitutivo, evitando l'errore. Un'altra opzione è utilizzare la libreria `chardet` per rilevare automaticamente l'encoding del file, anche se non è sempre affidabile al 100%. Per casi particolarmente complicati, valuta di utilizzare librerie come `json5` o `ujson`, che a volte offrono maggiore flessibilità nella gestione degli errori.
Avatar di perseorossi81
Per risolvere l'UnicodeDecodeError senza conoscere a priori l'encoding, prova a impostare `encoding='utf-8-sig'` per bypassare il BOM iniziale o usa `errors='surrogateescape'` al posto di `'replace'`/`'ignore'`: è meno invasivo e permette di recuperare i dati originali se necessario. Se fallisce ancora, leggi il file in modalità binaria, decodifica manualmente con `'utf-8'` e gestisci i byte sospetti (es. `file.read().decode('utf-8', errors='surrogateescape')`).

La libreria `chardet` funziona, ma è lenta e approssimativa. Meglio `cchardet` o `charset_normalizer` se devi processare molti file. Per JSON con emoji o dati mobili, assicurati che l'API invii veramente UTF-8: a volte il problema è nella risposta HTTP non correttamente decodificata (es. `.content` invece di `.text` in `requests`).

Se vuoi forza bruta, usa `ujson.load()` che è più tollerante, ma occhio a potenziali bug. Ultima spiaggia: apri il file con `encoding='latin1'` (che accetta tutti i byte) e poi ricodificalo in UTF-8 dopo la lettura. Funziona se i caratteri sono validi ma l'encoding dichiarato male.
Avatar di riccardagentile
Aggiungerei un passo pratico: dopo aver impostato `errors='surrogateescape'`, fai un controllo manuale su eventuali caratteri strani nei dati caricati. Le emoji problematiche spesso si nascondono in campi poco ovvi (es. meta-dati ISO o note interne dell'API). Se proprio non riesci a decodificare, prova a leggere in binario con `open('dati.json', 'rb')`, decodifica con `file.read().decode('utf-8', errors='backslashreplace')` e lavora sulla stringa risultante. Personalmente, in casi estremi uso `ujson.load()` che è più elastico, ma attenzione: a volte trasforma gli errori in valori null senza avvisare. Se la cosa si ripete spesso, valuta di normalizzare l'output dell'API alla fonte (es. forzando UTF-8 nel middleware). Ah, e non dimenticare di controllare se il file JSON ha un BOM iniziale – capita spesso con origini Windows/miste.
Avatar di luxbernardi
Grazie Riccardo, ottimi spunti! Il controllo manuale sui meta-dati è fondamentale, infatti ho trovato emoji "nascoste" nei campi descrittivi.
Proverò la tua strategia binaria con `backslashreplace` per non perdere dati grezzi. L'opzione di normalizzare in middleware mi convince, risolverebbe alla radice - domani contatto il team API.
*ujson* non lo conoscevo, ma la tua nota sui valori null è preziosa: meglio gestire gli errori esplicitamente. E sì, il BOM c'era in un file da loro sistema legacy Windows!
**Aggiornamento**: combinando `errors='surrogateescape'` e controllo del BOM, ora lo script digerisce tutti i file.
Avatar di sennacoppola
Sì, @luxbernardi, hai fatto un ottimo lavoro implementando le strategie discusse. L'approccio di lettura binaria con `backslashreplace` è solido per mantenere i dati originali, e aver individuato il BOM in alcuni file è stato un passo cruciale. La normalizzazione a livello di middleware è sicuramente la soluzione più robusta a lungo termine. Se il team API è collaborativo, dovresti riuscire a risolvere definitivamente il problema. Una nota: se prevedi di gestire grandi volumi di dati, valuta anche l'uso di librerie come `cchardet` o `charset_normalizer` per rilevare l'encoding in modo più efficiente. Complimenti per l'aggiornamento positivo dello script!

La Tua Risposta

💬

Vuoi partecipare alla discussione?

Accedi o registrati per scrivere la tua risposta e unirti alla conversazione!