JSON Toolkit

JSON5 e JSONC: JSON con commenti

In sintesi: Entrambi i dialetti esistono perché le configurazioni scritte dalle persone richiedono commenti e virgole finali, ma sintassi e portata nell'ecosistema differiscono, quindi scegliere male blocca la toolchain.

Principiante~10 min di letturaPubblicato il 2026-10-30Aggiornato il 2026-10-30
Copertina di JSON5 e JSONC, JSON con commenti

In sintesi: usa JSONC per i commenti dentro le configurazioni di VS Code e TypeScript, usa JSON5 quando ti serve la sintassi dei letterali ES5.1 più ampia come apici singoli o chiavi senza virgolette, e mantieni le API pubbliche su JSON standard.

Il JSON standard non ammette commenti, quindi ogni team li scrive comunque di nascosto — finché un giorno la build si rompe. Invece di farlo di nascosto, scegli un dialetto adeguato.

1. I due dialetti hanno motivazioni diverse

  • JSONC (JSON with Comments): JSON standard più commenti e virgole finali, con quasi nessun'altra modifica sintattica. È lo standard de facto dell'ecosistema VS Code — settings.json, tsconfig.json e .eslintrc.json lo usano tutti.
  • JSON5: molto più ambizioso, allineato direttamente al letterale oggetto ES5.1 — apici singoli, chiavi senza virgolette, esadecimale, Infinity/NaN, continuazione di riga con barra rovesciata e segni + iniziali.

Una frase per distinguerli: JSONC rende solo più comodo scrivere; JSON5 ti permette di scrivere un file di configurazione come se fosse JavaScript.

2. Tabella comparativa della sintassi

Funzionalità JSON standard JSONC JSON5
Commenti // /* */ ✗ ✓ ✓
Virgole finali ✗ ✓ ✓
Stringhe con apici singoli ✗ ✗ ✓
Chiavi senza virgolette ✗ ✗ ✓
Numeri esadecimali ✗ ✗ ✓
Punto decimale iniziale/finale .5 5. ✗ ✗ ✓
Numeri che iniziano con + ✗ ✗ ✓
Infinity / NaN ✗ ✗ ✓
Continuazione \ a fine riga ✗ ✗ ✓
Stringhe multiriga ✗ ✗ ✓ (implementate tramite continuazione)
Valore di livello superiore arbitrario ✓ ✓ ✓

La specifica completa di JSON5 supera di poco una pagina; il pacchetto json5 è mantenuto da tempo dalla comunità, e browser e Node si comportano allo stesso modo.

3. Parsing: due API, due tipi di capacità di localizzazione

3.1 JSON5: parsing semplice dell'intero documento

import JSON5 from 'json5';

const config = JSON5.parse(`
{
  // service port
  port: 8080,
  host: '0.0.0.0',
  features: ['json5', 'jsonc',],
  retries: 0x10,
}
`);

console.log(config.port, config.retries); // 8080 16

JSON5.parse restituisce un oggetto semplice senza informazioni di offset — perché non è pensato per gli scenari di modifica, ma solo per "leggere la configurazione".

3.2 JSONC: un albero sintattico con offset

Il valore di jsonc-parser non sta nel parsing ma nella modifica. Offre tre livelli di API:

API Scopo Uso tipico
parse Analizza in un albero che porta offset/length Evidenziazione della sintassi, folding, navigazione
visit Attraversamento in profondità; il callback riceve il percorso del nodo Ispezione simile a JSONPath
modify + applyEdits Produce una modifica testuale minima, poi la applica al testo originale Cambiare un valore mantenendo i commenti
import { parseTree, findNodeAtLocation, modify, applyEdits } from 'jsonc-parser';

const text = `{
  // port configuration
  "server": {
    "port": 8080 // 80 in production
  }
}`;

const tree = parseTree(text);
const portNode = findNodeAtLocation(tree!, ['server', 'port']);
console.log(portNode?.offset, portNode?.length);

const edits = modify(text, ['server', 'port'], 3000, {
  formattingOptions: { insertSpaces: true, tabSize: 2 },
});
console.log(applyEdits(text, edits));

L'output conserva i commenti originali e sostituisce solo i tre caratteri di 8080:

{
  // port configuration
  "server": {
    "port": 3000 // 80 in production
  }
}

Questo è esattamente ciò che "modificare la configurazione con espressioni regolari" non può fare: una regex non sa quale 8080 cambiare, e non sa che il 8080 dentro una stringa deve essere lasciato stare.

3.3 I messaggi di errore devono portare gli offset

I codici di errore di jsonc-parser sono valori di enum; quelli comuni sono:

Codice di errore Significato
InvalidSymbol È comparso un carattere che non dovrebbe esserci
PropertyNameExpected Era atteso un nome di chiave
ColonExpected Era atteso un carattere due punti
CommaExpected Era attesa una virgola
CloseBraceExpected L'oggetto non è stato chiuso
UnexpectedEndOfComment Il commento non è stato chiuso
InvalidEscapeCharacter Escape non valido

Una volta convertito offset in riga e colonna, l'editor può disegnare la sottolineatura esattamente sulla posizione colpevole.

4. Quando usare l'uno o l'altro

Scenario Raccomandazione Motivo
Corpi di richiesta/risposta delle API pubbliche JSON standard I dialetti non sono supportati dai client generici
package.json, composer.json JSON standard I package manager capiscono solo JSON standard
tsconfig.json, .vscode/settings.json JSONC Il valore predefinito dell'ecosistema, supportato nativamente dalla toolchain
Configurazione applicativa (richiede commenti) JSONC o YAML I commenti devono essere preservati mentre gli strumenti possono ancora leggerla e scriverla
Necessità di Infinity, esadecimale, letterali complessi JSON5 Il potere espressivo più forte
Scambio di dati, log, cache JSON a righe o standard Streaming e universalità sono richiesti

Regola pratica: se il file verrà letto da uno "strumento non umano", preferisci JSON standard; considera un dialetto solo quando sei certo che venga letto esclusivamente dal tuo codice.

5. Tre tipi di rischio introdotti dai dialetti

5.1 Effetto valanga del requisito

Quando un altro strumento legge un file JSON5 e chiama JSON.parse, va in crash immediato. Il sintomo tipico è "funziona in locale, fallisce su Docker" — perché il container esegue un percorso di lettura diverso.

Contromisura: aggiungi al repository un controllo CI che elenchi esplicitamente quali file possono usare un dialetto; tutto il resto viene validato come JSON standard.

5.2 Sorprese intorno all'inferenza dei tipi

JSON5 consente chiavi senza virgolette e apici singoli, ma non ti permette di introdurre costrutti come date o espressioni regolari — è comunque un formato di dati, non valutazione JavaScript. C'è chi ha pensato che JSON5 potesse esprimere new Date() solo per vedere il parsing fallire. JSON5 non è eval.

5.3 Commenti eliminati in silenzio

Né JSON5.stringify né JSON.stringify preservano i commenti. Quindi "leggi, ritocca un valore, riscrivi" elimina ogni commento. Quando i commenti devono sopravvivere, le uniche opzioni sono l'API di modifica di jsonc-parser, oppure una libreria YAML che supporta la preservazione dei commenti.

6. Raccomandazioni pratiche

  • [ ] Mantieni nella documentazione del team una tabella "tipo di file → formato" così che nessuno improvvisi;
  • [ ] Avvolgi la lettura della configurazione in un unico loadConfig() che decida internamente quale parser usare, così il codice di business non chiama mai JSON.parse direttamente;
  • [ ] Quando modifichi programmaticamente una configurazione con commenti, usa modify + applyEdits; non riscrivere mai l'intero file;
  • [ ] Valida in CI anche i file di dialetto (jsonc-parser per JSONC, JSON5.parse per JSON5), altrimenti gli errori di sintassi emergono solo a runtime;
  • [ ] Usa JSON standard per le interfacce pubbliche, le chiavi di cache e i payload dei code.

FAQ

Come scelgo tra JSON5 e JSONC?

Scegli in base al runtime più che al numero di sintassi: VS Code, TypeScript ed ESLint leggono JSONC per impostazione predefinita, quindi JSONC offre la migliore compatibilità; ricorri a JSON5 solo quando ti serve la sintassi dei letterali ES5.1 più ampia, come apici singoli, chiavi senza virgolette o Infinity. Nessuno dei due dialetti è adatto alle risposte delle API pubbliche.

Perché un parser JSON standard non può leggere JSONC direttamente?

JSONC consente commenti e virgole finali, mentre JSON.parse accetta solo JSON RFC 8259 e solleva un errore in entrambi i casi. Leggere JSONC richiede un parser come jsonc-parser, oppure rimuovere i commenti prima di passare il testo a un parser standard.

I commenti in JSONC devono sopravvivere alle modifiche del file?

Sì, ma solo tramite un'API di modifica. modify e applyEdits di jsonc-parser cambiano il nodo di destinazione preservando i commenti rimanenti; analizzare in un oggetto e serializzarlo elimina ogni commento.