← Tutti gli articoli

Come gestire JSON rotto in JavaScript

Il JSON reale è spesso sporco: virgole finali, apici singoli, letterali Python, fence di markdown. Impara i pattern comuni, come scrivere un helper di parsing sicuro e quando passare a una libreria di riparazione dedicata.

Ogni sviluppatore JavaScript l'ha visto: JSON.parse() lancia un SyntaxError e la tua applicazione crasha. Il JSON è arrivato da un'API, un file di config o la clipboard di un utente —— e semplicemente non parsa. In questa guida ripercorriamo esattamente perché succede, com'è fatto un JSON rotto nel mondo reale, e come gestirlo con grazia —— da un semplice try/catch alla riparazione automatica.

1. Perché JSON.parse() fallisce

Lo standard JSON (RFC 8259) è deliberatamente stretto. JSON.parse() lo implementa esattamente —— qualsiasi deviazione, per quanto minore, lancia un SyntaxError senza recupero parziale:

try {
  const data = JSON.parse('{ name: "Ada" }'); // chiave non quotata
} catch (err) {
  console.error(err.message);
  // SyntaxError: Expected property name or '}' in JSON at position 2
}

A differenza di un browser che parsa HTML (che ha un modello di recupero errori integrato), il parser JSON è un cancello rigido. Il parsing stretto è una feature: forza i produttori a emettere dati puliti. Ma quando non controlli la sorgente dei dati —— output di LLM, file di config modificati a mano, API di terze parti —— ti serve una strategia per quando quel cancello sbatte chiuso.

2. I pattern più comuni di JSON rotto

Prima di acchiappare una libreria di riparazione, aiuta riconoscere con cosa hai a che fare. Quasi tutti i JSON rotti del mondo reale cadono in una di queste categorie:

Virgolette singole invece di doppie

// ❌ JSON non valido
{ 'name': 'Ada Lovelace' }

// ✅ Valido
{ "name": "Ada Lovelace" }

I letterali di oggetto JavaScript accettano le virgolette singole; JSON no. Gli sviluppatori copiano un letterale di oggetto direttamente in un contesto JSON e incappano in questo errore di continuo.

Virgole finali

// ❌ JSON non valido
{
  "name": "Ada",
  "active": true,   // virgola finale
}

// ✅ Valido
{
  "name": "Ada",
  "active": true
}

JavaScript moderno consente virgole finali in array e oggetti. JSON no. È l'errore singolo più comune nei file JSON modificati a mano.

Chiavi di oggetto non quotate

// ❌ JSON non valido
{ name: "Ada", score: 98 }

// ✅ Valido
{ "name": "Ada", "score": 98 }

I letterali di oggetto JavaScript non richiedono chiavi quotate. JSON richiede che tutte le chiavi siano stringhe tra virgolette doppie, senza eccezioni.

Commenti JavaScript

// ❌ JSON non valido
{
  // questo è il record utente
  "name": "Ada",
  /* aggiunto nel 2024 */
  "active": true
}

JSON non ha sintassi di commenti. I commenti vengono talvolta aggiunti ai file di config (JSONC —— JSON-with-Comments —— è un'estensione popolare), ma JSON.parse() li rifiuta.

Stringhe multi-riga

// ❌ JSON non valido
{
  "description": "line one
  line two"
}

// ✅ Valido —— escape della nuova riga
{
  "description": "line one\nline two"
}

I valori string in JSON devono stare su una sola riga. Le nuove righe letterali dentro una stringa non sono ammesse; usa la sequenza di escape \n al posto.

NaN, Infinity e undefined

// ❌ Non è JSON valido
{ "ratio": NaN, "limit": Infinity, "value": undefined }

// ✅ Alternative valide
{ "ratio": null, "limit": 1e308, "value": null }

Sono valori JavaScript validi ma non parte della specifica JSON. JSON.stringify() li converte silenziosamente (NaN e Infinity diventano null; le proprietà undefined vengono scartate del tutto), il che può causare bug sottili di round-trip.

Letterali Python

// ❌ Stile Python —— JSON non valido
{ "active": True, "deleted": False, "value": None }

// ✅ JSON valido
{ "active": true, "deleted": false, "value": null }

JSON è stato progettato per interoperare tra più linguaggi. I True, False e None di Python con la lettera maiuscola sono una fonte frequente di bug cross-language.

3. «Riparare» e «parsare» non sono la stessa cosa

È importante distinguere tra due operazioni fondamentalmente diverse:

  • Parsing stretto —— validare che l'input sia esattamente JSON corretto, riportare la posizione precisa di ogni errore, rifiutare qualsiasi cosa devii. Usa quando controlli il produttore dei dati e vuoi imporre un contratto.
  • Parsing con riparazione —— tentare di recuperare un valore JSON valido da un input sintatticamente imperfetto usando un insieme di regole euristiche. Usa quando i dati vengono da una fonte non affidabile o imprecisa (output LLM, clipboard utente, servizio legacy).

Un parser di riparazione fa supposizioni. Se incontra True assume che intendessi true. Se incontra una virgola finale la rimuove. Queste supposizioni sono quasi sempre corrette per i pattern elencati sopra —— ma possono mascherare silenziosamente un documento davvero malformato dove il «fix» cambia il significato voluto.

Lo strumento giusto dipende dal contesto. In una pipeline di risposte API validate da schema, vuoi parsing stretto così i dati cattivi emergano immediatamente. In uno strumento dev dove un umano sta incollando JSON copiato da un messaggio Slack, il parsing con riparazione fa risparmiare tempo.

Librerie da conoscere

Due pacchetti npm fanno la maggior parte del lavoro pesante, con trade-off complementari:

  • jsonrepair —— un parser di riparazione tollerante. Gli passi JSON cattivo e ottieni una stringa valida best-effort. Gestisce i pattern di cui sopra (virgolette singole, virgole finali, chiavi non quotate, commenti, letterali Python, fence di markdown, parentesi non chiuse, input parziale). Sincrono, zero dipendenze, piccolo —— ideale quando hai un documento completo in memoria.
  • clarinet —— un parser JSON streaming stile SAX. Usalo quando il JSON arriva in chunk (uno stream, un file grande, una risposta LLM token per token) e devi reagire mentre chiavi/valori appaiono invece di aspettare il documento intero. È stretto sulla sintassi, quindi accoppialo a jsonrepair se la sorgente non è affidabile.

Regola pratica: ripara quando hai un blob piccolo e non affidabile; streamma quando il documento è grande o arriva progressivamente.

4. Catturare gli errori e dare feedback amichevole agli utenti

Il pattern minimo viable è un try/catch. Fallo sempre —— non lasciare mai che JSON.parse() lanci senza essere catturato:

function safeParseJson(text) {
  try {
    return { ok: true, value: JSON.parse(text) };
  } catch (err) {
    return { ok: false, error: err.message };
  }
}

const result = safeParseJson(userInput);
if (!result.ok) {
  showError(`Could not parse JSON: ${result.error}`);
}

Il messaggio di errore di JSON.parse() varia in base all'engine JavaScript. V8 (Node.js, Chrome) include un suggerimento di posizione:

// Messaggio di errore V8
"Expected ',' or '}' after property value in JSON at position 42"

// Firefox SpiderMonkey
"JSON.parse: expected ',' or '}' after property value in object
at line 3 column 5 of the JSON data"

L'informazione di posizione è utile ma specifica dell'engine. Se ti serve un reporting riga/colonna affidabile attraverso gli ambienti, un parser a discesa ricorsiva custom può emettere errori strutturati molto più facili da mostrare agli utenti.

5. Quando auto-riparare vs. chiedere conferma

Non tutte le riparazioni hanno lo stesso rischio. Ecco un'euristica pratica:

  • Sicuro da riparare automaticamente —— virgole finali, normalizzazione di spazi bianchi, conversione di stile delle virgolette, chiavi non quotate, commenti JavaScript, letterali boolean/null Python. Sono trasformazioni meccaniche senza ambiguità semantica.
  • Considera di chiedere all'utente —— riparazioni strutturali come auto-chiudere un oggetto o array non chiuso ({"name": "Ada"{"name": "Ada"}), o rimuovere contenuto (cancellare un commento che sembra intenzionale). La riparazione è probabilmente giusta, ma l'utente potrebbe voler verificare.
  • Sempre segnala, mai correggere in silenzio —— coercizioni di tipo come NaN → null cambiano il valore del dato. Mostra all'utente cosa è cambiato.

Una buona UI di riparazione mostra un diff: l'input originale a sinistra, l'output riparato a destra. L'utente può confermare che la correzione è giusta prima di copiare o inviare il risultato.

6. Il vantaggio di privacy del processing JSON nel browser

Quando processi JSON localmente nel browser —— usando l'engine JavaScript che sta già facendo girare la pagina —— i dati non lasciano mai la macchina dell'utente. Questo conta più di quanto gli sviluppatori spesso si rendano conto:

  • API key e credenziali —— gli sviluppatori incollano regolarmente payload JSON che contengono segreti. Uno strumento lato server logga ogni richiesta.
  • PII e dati sanitari —— la conformità a GDPR e HIPAA diventa molto più semplice quando non c'è trasferimento dati.
  • Dati aziendali —— molte policy di sicurezza vietano di incollare dati interni in servizi web di terze parti.

Il processing nel browser ti dà riparazione JSON a rischio zero: niente server, niente log, niente retention dei dati. Il calcolo avviene in un <textarea> e pochi kilobyte di JavaScript.

Domande frequenti

Come gestisco un errore di JSON.parse in JavaScript?

Avvolgi la chiamata in try/catch e ritorna un risultato strutturato invece di lasciare il SyntaxError propagarsi (vedi l'helper safeParseJson sopra). Non chiamare mai JSON.parse() su input non fidato senza un guard.

C'è un modo per parsare JSON rotto automaticamente?

Sì —— un parser di riparazione recupera un valore valido da input imperfetto applicando euristiche (rimuovere virgole finali, convertire virgolette singole, mettere in minuscolo True). Usalo per fonti non fidate come output LLM o testo incollato, non per risposte API validate da contratto dove vuoi che i dati cattivi emergano.

Quando dovrei riparare JSON vs. rifiutarlo?

Ripara quando un umano ha incollato JSON approssimativo o un LLM l'ha prodotto; rifiuta (parsing stretto) quando controlli il produttore e vuoi imporre uno schema. Coercizioni di tipo come NaN → null dovrebbero sempre essere segnalate, mai applicate in silenzio.

Qual è la causa più comune di JSON rotto?

Trattare un letterale di oggetto JavaScript come JSON —— virgolette singole, chiavi non quotate e virgole finali. Vedi JSON vs oggetti JavaScript e il riferimento agli errori di sintassi in [object Object] e altri errori.

7. Provalo subito —— incolla il tuo JSON rotto

Se hai una stringa JSON malformata da sistemare subito, JSON Fix gestisce tutti i pattern di cui sopra —— virgolette singole, virgole finali, chiavi non quotate, letterali Python, commenti, fence di codice markdown e altro. Tutto gira nel tuo browser; niente viene inviato a un server.