Incolli qualcosa che sembra dato valido in un parser JSON e lui lancia subito SyntaxError: Unexpected token '''. I dati vengono dal tuo codice JavaScript e sembrano del tutto ragionevoli —— ma JSON e gli object literal JavaScript non sono lo stesso formato, e le differenze contano più di quanto la maggior parte degli sviluppatori realizzi.
La risposta breve: JSON non supporta le virgolette singole
Le virgolette singole sono nettamente illegali in JSON. Ogni stringa —— sia key che valori —— deve usare virgolette doppie. Nessuna eccezione.
// ❌ JSON non valido —— stringhe con virgolette singole
{ 'name': 'Ada Lovelace', 'active': true }
// ✅ JSON valido
{ "name": "Ada Lovelace", "active": true }L'errore che vedrai in vari ambienti:
// Chrome / Node.js (V8)
SyntaxError: Unexpected token "'", "{'name':..." is not valid JSON
// Firefox
SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data
// Safari
SyntaxError: JSON Parse error: Single quotes (') are not allowed in JSONIl messaggio di Safari è il più utile —— ti dice esattamente qual è il problema. Gli altri segnalano solo il carattere inatteso.
Perché JSON richiede virgolette doppie?
JSON è stato definito da Douglas Crockford nel 2001 e standardizzato come RFC 8259. La grammatica specifica esattamente un delimitatore di stringa: il carattere virgoletta doppia (U+0022). Le virgolette singole semplicemente non sono nella grammatica.
Il motivo è semplicità. JSON è un formato di scambio dati pensato per essere parsato da qualsiasi linguaggio, non solo JavaScript. Imponendo un singolo stile di quoting, la spec elimina un'intera classe di ambiguità. I parser in Go, Python, Java, Rust e qualsiasi altro linguaggio implementano esattamente la stessa regola.
JSON vs object literal JavaScript: le differenze complete
Le virgolette singole sono solo una di parecchie differenze. Ecco il quadro completo:
1. Le key devono essere stringhe tra virgolette doppie
// ❌ Object literal JavaScript —— key nuda, key con virgolette singole
{ name: "Ada", 'score': 98 }
// ✅ JSON —— tutte le key sono stringhe tra virgolette doppie
{ "name": "Ada", "score": 98 }Gli object literal JavaScript accettano identificatori nudi, stringhe con virgolette singole e stringhe con virgolette doppie come key. JSON accetta solo stringhe con virgolette doppie.
2. Niente virgole finali
// ❌ JSON non valido
{ "name": "Ada", "score": 98, }
// ^ virgola finale
// ✅ JSON valido
{ "name": "Ada", "score": 98 }JavaScript moderno consente esplicitamente le virgole finali. JSON no —— vedi la nostra guida completa sulle virgole finali in JSON.
3. Niente commenti
// ❌ JSON non valido
{
// profilo utente
"name": "Ada"
}
// ✅ JSON non ha sintassi di commenti
{ "name": "Ada" }JSON non ha nessuna sintassi di commenti. Se ti servono commenti nei file di config, considera il formato JSONC (JSON-with-Comments), supportato dalle settings di VS Code, dal tsconfig.json di TypeScript e diversi parser di file di config.
4. Niente undefined, funzioni o symbol
// Oggetto JavaScript —— accetta valori non serializzabili
const obj = {
fn: () => 42, // funzione
sym: Symbol('id'), // Symbol
val: undefined, // undefined
};
// JSON.stringify li scarta o converte silenziosamente
JSON.stringify(obj);
// → '{}' (tutte e tre le proprietà spariscono o diventano null) JSON supporta esattamente sei tipi di valore: string, number, boolean (true/false), null, object e array. Funzioni, Symbol e undefined non hanno rappresentazione JSON. JSON.stringify() scarta silenziosamente le proprietà di oggetto con questi valori e li converte in null all'interno degli array.
5. Niente NaN o Infinity
JSON.stringify({ ratio: NaN, limit: Infinity });
// → '{"ratio":null,"limit":null}'
// NaN e Infinity diventano null —— silenziosamente!
JSON.parse('{"ratio": NaN}');
// → SyntaxError: Unexpected token 'N'NaN e Infinity sono valori numerici JavaScript validi ma non fanno parte della specifica numerica di JSON. JSON.stringify() li converte in null in uscita; JSON.parse() li rifiuta in entrata. Questa asimmetria è una fonte comune di bug sottili.
6. Numeri: niente hex, niente zeri iniziali, niente +
// ❌ JSON non valido
{ "flags": 0xFF, "code": 007, "delta": +1.5 }
// ✅ JSON valido
{ "flags": 255, "code": 7, "delta": 1.5 } I numeri JSON devono essere decimali, non possono iniziare con un segno + esplicito, e non possono avere zeri iniziali (eccetto la singola cifra 0 prima di un punto decimale). I letterali esadecimali e ottali non sono JSON valido.
7. Niente stringhe multi-riga
// ❌ JSON non valido —— nuova riga letterale nella stringa
{ "bio": "Line one
Line two" }
// ✅ Usa la sequenza di escape
{ "bio": "Line one\nLine two" }8. Key computate, key Symbol e shorthand di metodo
Altre tre feature solo-JS che sembrano JSON ma non hanno equivalente:
// ❌ Nomi di proprietà computati —— valutati, non letterali
const k = "id";
const obj = { [k]: 1, [`user_${k}`]: 1 };
// JSON non ha espressioni; la key deve essere una stringa letterale tra virgolette doppie.
// ❌ Key Symbol —— scartate silenziosamente da JSON.stringify
const tag = Symbol('tag');
JSON.stringify({ [tag]: 'admin' }); // → '{}'
// ❌ Shorthand di metodo —— le funzioni vengono scartate/omesse
const obj = { greet() { return 'hi'; } };
JSON.stringify(obj); // → '{}' Se hai bisogno di una di queste, serializza una proiezione in forma JSON del tuo oggetto —— JSON.stringify() produce solo key stringa e i sei tipi di valore JSON.
Una cheatsheet veloce di conversione
| Object literal JavaScript | Equivalente JSON valido |
|---|---|
{ name: "Ada" } | {"name":"Ada"} |
{ 'name': 'Ada' } | {"name":"Ada"} |
{ a: 1, } | {"a":1} |
{ val: undefined } | {} (proprietà scartata) |
{ n: NaN } | {"n":null} |
{ n: Infinity } | {"n":null} |
{ fn: () => 1 } | {} (proprietà scartata) |
0xFF | 255 |
Il modo più sicuro di convertire un oggetto JS in JSON
Non provare mai a convertire un oggetto JavaScript in JSON modificando le virgolette a mano. Usa JSON.stringify() —— gestisce ogni caso limite correttamente:
const obj = { name: 'Ada', score: 98, active: true };
// Compatto
JSON.stringify(obj);
// → '{"name":"Ada","score":98,"active":true}'
// Pretty-print con indent a 2 spazi
JSON.stringify(obj, null, 2);
// → '{
"name": "Ada",
"score": 98,
"active": true
}' Il secondo argomento di JSON.stringify() è un replacer —— puoi passare un array di nomi di key per includere solo quelle proprietà, o una funzione per trasformare i valori:
// Includere solo key specifiche
JSON.stringify(obj, ['name', 'score'], 2);
// → '{
"name": "Ada",
"score": 98
}'
// Replacer custom —— convertire undefined in null
JSON.stringify({ a: 1, b: undefined }, (key, value) =>
value === undefined ? null : value
);
// → '{"a":1,"b":null}'Quando ricevi un object literal JS come stringa
A volte ricevi dati che sembrano JSON ma sono in realtà un object literal JavaScript —— magari da un file di log, uno strumento di debug, o un'API che non rispettava la spec. In tal caso JSON.parse() fallisce e hai due opzioni:
- Usa un parser di riparazione —— converte virgolette singole in doppie, rimuove virgole finali, mette tra virgolette le key nude, e gestisce automaticamente tutte le altre differenze. L'approccio più sicuro per input non fidati.
- Usa
eval()oFunction()—— tecnicamente funziona per JavaScript valido, ma è un serio rischio di sicurezza se la fonte non è pienamente fidata. Non farlo mai con input fornito dall'utente.
Domande frequenti
JSON supporta le virgolette singole?
No. La grammatica JSON (RFC 8259) definisce esattamente un delimitatore di stringa —— la virgoletta doppia. Sia key che valori devono usare virgolette doppie; le virgolette singole lanciano un SyntaxError.
Qual è la differenza tra JSON e un oggetto JavaScript?
JSON è un formato testuale stretto; un object literal JavaScript è codice permissivo. JS consente virgolette singole, key senza virgolette, virgole finali, commenti, undefined, NaN, funzioni e numeri esadecimali —— nessuno dei quali è JSON valido. Vedi la cheatsheet completa sopra e il primer in Cos'è JSON?
Come converto un oggetto JavaScript in JSON?
Usa JSON.stringify() —— non modificare mai le virgolette a mano. Gestisce ogni caso limite, scarta valori non serializzabili e fa escape delle stringhe correttamente.
Perché non posso usare eval() per parsare un object literal JS?
eval() esegue codice arbitrario, quindi è un serio rischio di sicurezza su input non fidati. Usa invece un parser di riparazione (o JSON Fix) per convertire un object literal JS in JSON valido in modo sicuro.
Risolvi le virgolette singole all'istante
Se hai un object literal JavaScript da convertire in JSON valido subito, JSON Fix gestisce la conversione automaticamente. Converte virgolette singole in doppie, mette tra virgolette le key nude, rimuove virgole finali e sistema tutte le altre differenze elencate sopra —— nel tuo browser, senza dati inviati a nessun server.
- JSON Fix —— converti object literal JS in JSON valido all'istante
- Risolvere virgolette singole in JSON —— guida di riferimento rapida con esempi rotti e corretti
- JSON vs Object Literal JavaScript —— ogni differenza di sintassi con esempi fianco a fianco
- Errori Unexpected Token di JSON.parse —— una guida a ogni variante del SyntaxError che potresti vedere
- Virgole finali in JSON —— perché sono consentite in JS ma proibite in JSON