Quando il JSON stretto ti fa fare debug fino a notte fonda per una virgola mancante, potrebbe essere il momento di incontrare i suoi cugini più permissivi — JSON5 e JSON with Comments (JSONC).
Cos’è JSON5?
JSON5 è un’estensione di JSON che incorpora funzionalità da ECMAScript 5.1, incluse chiavi senza virgolette, virgole finali, stringhe tra apici singoli, commenti e numeri esadecimali. È mantenuto dalla community e progettato per rendere i file di configurazione scritti a mano più leggibili e permissivi del JSON stretto.
Cos’è JSONC?
JSONC (JSON with Comments) è un’estensione minimale del JSON standard che aggiunge supporto per commenti su una riga (//) e su più righe (/* */). Le virgole finali, invece, non sono sempre ammesse: dipende dal parser. È il formato nativo per le impostazioni di VS Code, tsconfig.json e altri file di configurazione TypeScript.
Perché abbiamo bisogno di JSON “permissivo”
- Colli di bottiglia di leggibilità: Il JSON standard vieta commenti, virgole finali, apici singoli, ecc., il che danneggia la chiarezza in config e demo.
- Dolori della collaborazione di team: File JSON enormi senza note inline sono difficili da mantenere; una piccola modifica può rompere l’intero file.
- Realtà DevOps: Kubernetes e le pipeline CI/CD spesso uniscono o generano JSON al volo; una sintassi permissiva taglia le correzioni manuali.
JSON5 vs. JSONC a colpo d’occhio
| Funzionalità | JSON (RFC 8259) | JSONC | JSON5 |
|---|---|---|---|
Commenti // e /* */ | No | Sì | Sì |
| Virgole finali | No | Dipende dal parser (vedi sotto) | Sì, una per oggetto o array |
| Chiavi senza virgolette | No | No | Sì |
| Stringhe tra apici singoli | No | No | Sì |
| Stringhe su più righe (a capo con escape) | No | No | Sì |
Numeri esadecimali (0x1F) | No | No | Sì |
.5, 5., + iniziale | No | No | Sì |
Infinity, NaN | No | No | Sì |
Numeri binari (0b101) | No | No | No |
| Specifica | RFC 8259 / ECMA-404 | Nessuno standard formale; definito di fatto da VS Code e jsonc-parser | Spec JSON5 1.0.0 |
Letto da JSON.parse / json.loads integrati | Sì | No | No |
Fonti: la spec JSON5, la documentazione JSON di VS Code e RFC 8259. La riga sui numeri binari l’abbiamo verificata: JSON5.parse('{a: 0b101}') con json5 2.2.3 fallisce con JSON5: invalid character 'b' at 1:6.
In una frase: JSON5 sembra un letterale di oggetto JavaScript, mentre JSONC è JSON normale che tollera i commenti: chiavi e stringhe vanno comunque tra virgolette doppie.
Virgole finali in JSONC: dipende dal parser
JSONC non ha una specifica ufficiale. Microsoft lo ha introdotto in modo informale per i file di configurazione di VS Code e ha rilasciato insieme jsonc-parser. Una bozza della community su jsonc.org cerca di formalizzarlo, ma sulle virgole finali dice solo che i parser “MAY support trailing commas” (possono supportarle). E infatti gli strumenti reali si comportano in modo diverso:
| Parser o strumento | Virgola finale | Fonte |
|---|---|---|
| VS Code, modalità JSON with Comments | Accettata, con un avviso | Documentazione di VS Code |
jsonc-parser 3.3.1, opzioni predefinite | Segnalata con gli errori PropertyNameExpected / ValueExpected, ma un valore viene comunque restituito | Test più avanti |
jsonc-parser 3.3.1, allowTrailingComma: true | Accettata | Test più avanti |
TypeScript 5.9.3 (tsc -p) | Accettata | Test sul tsconfig.json di esempio qui sotto |
Deno (deno.jsonc) | Accettata | Documentazione di configurazione di Deno |
Se il file deve essere accettato da qualsiasi lettore JSONC, evita le virgole finali.
Esempi di sintassi
JSON vanilla (stretto)
{
"name": "Go Tools",
"features": ["Base64", "JSON Formatter"]
}
Esempio JSON5
Un file JSON5, config.json5:
// configurazione di sviluppo
{
name: 'go-tools',
port: 0x1F90, // 8080 in esadecimale
tags: ['json', 'json5',],
}
Esempio JSONC
Un file JSONC, tsconfig.json:
{
// controllo dei tipi rigoroso
"compilerOptions": {
"strict": true,
"target": "ES2022", /* output moderno */
},
"include": ["src"],
}
Che formato ha il tuo file?
L’estensione da sola non basta: anche un file .json può essere analizzato come JSONC o JSON5. Controlla questa tabella, poi la documentazione dello strumento che legge il file.
| File | Formato | Note | Fonte |
|---|---|---|---|
tsconfig.json, jsconfig.json, tsconfig.*.json | JSONC | VS Code li apre in modalità JSONC; tsc 5.9.3 accetta commenti e virgole finali | Sorgente di VS Code (typescript-basics), nostro test |
.vscode/settings.json, tasks.json, launch.json | JSONC | Elencati tra i file JSON with Comments | Documentazione di VS Code |
devcontainer.json | JSONC | La spec lo definisce “a JSON with Comments file” (un file JSON con commenti) | Spec Dev Container |
deno.jsonc | JSONC | “with deno.jsonc you can add comments and trailing commas” (con deno.jsonc puoi aggiungere commenti e virgole finali) | Documentazione di Deno |
babel.config.json, .babelrc.json | JSON5, nonostante l’estensione .json | Babel li analizza come JSON5; VS Code li evidenzia come JSONC | Documentazione di Babel, sorgente di VS Code |
renovate.json5, .renovaterc.json5 | JSON5 | Anche renovate.json accetta JSONC | Documentazione di Renovate |
Qualsiasi file *.json5 | JSON5 | — | — |
package.json | JSON stretto | npm: “It must be actual JSON, not just a JavaScript object literal.” (deve essere vero JSON, non un semplice letterale di oggetto JavaScript) | Documentazione di npm, nostro test |
Babel non cerca un file babel.config.json5: .json5 non è tra le estensioni che documenta. Sono le varianti .json quelle che legge come JSON5.
Gli errori che vedrai, parola per parola
Abbiamo passato due piccoli file a ciascun runtime. comment.json contiene un commento:
{
// porta del server di sviluppo
"port": 8080
}
trailing.json ha una virgola finale:
{
"port": 8080,
}
Node.js 26.10.0, JSON.parse (Chrome Headless Shell 156 restituisce lo stesso testo, perché entrambi usano V8):
comment.json -> SyntaxError: Expected property name or '}' in JSON at position 4 (line 2 column 3)
trailing.json -> SyntaxError: Expected double-quoted property name in JSON at position 18 (line 3 column 1)
Python 3.13.5, json.loads:
comment.json -> json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
trailing.json -> json.decoder.JSONDecodeError: Illegal trailing comma before end of object: line 2 column 15 (char 16)
jq 1.7:
comment.json -> jq: parse error: Invalid numeric literal at line 2, column 5
trailing.json -> jq: parse error: Expected another key-value pair at line 3, column 1
npm 11.19.1, con una riga // comment in package.json:
npm error code EJSONPARSE
npm error JSON.parse Invalid package.json: JSONParseError: Expected property name or '}' in JSON at position 4 (line 2 column 3) while parsing near "{\n // comment\n \"name\":..."
npm error JSON.parse Failed to parse JSON data.
npm error JSON.parse Note: package.json must be actual JSON, not just JavaScript.
Come leggerli:
position 4 (line 2 column 3)indica la prima/del commento. Se l’errore cade all’inizio di una riga che comincia con//o/*, il file è quasi certamente JSONC o JSON5.- Sulle virgole finali, V8 e Python puntano in punti diversi. V8 segnala la
}di chiusura (riga 3), mentre Python 3.13.5 segnala la virgola stessa (riga 2, colonna 15). Altre versioni possono formulare i messaggi in modo diverso; il testo qui sopra è esattamente quello stampato da queste versioni. - Se l’errore cita un carattere che non vedi, come in
Unexpected token '', "{}" is not valid JSONdi Node 26 (in realtà entrambe le coppie di virgolette contengono un U+FEFF invisibile), molto probabilmente il file inizia con un byte order mark (BOM) invisibile, non con un commento. Vedi BOM UTF-8 ed errori di JSON.parse.
Conversione da JSONC o JSON5 a JSON standard
La conversione elimina tutti i commenti, perché in JSON non c’è posto per conservarli. Tieni il file commentato come sorgente e tratta l’output .json come un artefatto generato.
Node.js: da JSON5 a JSON con json5
// json5-to-json.mjs (installa con npm install json5)
import { readFileSync, writeFileSync } from 'node:fs';
import JSON5 from 'json5';
const data = JSON5.parse(readFileSync('config.json5', 'utf8'));
writeFileSync('config.json', JSON.stringify(data, null, 2) + '\n');
Eseguito con json5 2.2.3 sull’esempio JSON5 di sopra, config.json diventa:
{
"name": "go-tools",
"port": 8080,
"tags": [
"json",
"json5"
]
}
Node.js: da JSONC a JSON con jsonc-parser
jsonc-parser è il parser di Microsoft per JSON con commenti. La sua parse() non lancia eccezioni sugli errori di sintassi: raccoglie i problemi in un array errors e restituisce comunque il valore migliore che riesce a ricostruire, quindi quell’array devi controllarlo tu:
// jsonc-to-json.mjs (installa con npm install jsonc-parser)
import { readFileSync } from 'node:fs';
import { parse, printParseErrorCode } from 'jsonc-parser';
const errors = [];
const data = parse(readFileSync('tsconfig.json', 'utf8'), errors, {
allowTrailingComma: true,
});
if (errors.length > 0) {
for (const e of errors) console.error(printParseErrorCode(e.error), 'at offset', e.offset);
process.exit(1);
}
console.log(JSON.stringify(data, null, 2));
Con jsonc-parser 3.3.1 e l’esempio tsconfig.json di sopra, lo script stampa JSON pulito ed esce con codice 0. Senza allowTrailingComma: true, lo stesso file segnala PropertyNameExpected e ValueExpected in corrispondenza della } che segue subito ciascuna virgola finale.
Python: il pacchetto json5
Il modulo json della libreria standard non ha alcuna opzione per i commenti. Il pacchetto json5 legge JSON5, e quindi anche JSONC, dato che commenti e virgole finali sono entrambi validi in JSON5:
# installa con pip install json5
import json
import json5
with open("tsconfig.json", encoding="utf-8") as f:
data = json5.load(f)
print(json.dumps(data, indent=2, ensure_ascii=False))
Testato con Python 3.13.5 e json5 0.17.3, stampa lo stesso JSON della versione Node.
Riga di comando: la CLI json5
Il pacchetto npm json5 include una CLI che converte in JSON e valida. Legge anche i file JSONC:
npx json5 config.json5 # JSON compatto su stdout
npx json5 -s 2 -o config.json config.json5 # indentato, scritto su file
npx json5 -v tsconfig.json # solo validazione; codice di uscita 1 se trova un errore di sintassi
Poiché con -v il codice di uscita è 1 in caso di errore di sintassi, lo stesso comando funziona come step di CI che controlla i file JSON5 o JSONC modificati a mano.
jq qui non aiuta: come visto sopra, jq 1.7 si ferma al primo commento.
Attenzione a Infinity e NaN
JSON5 ammette Infinity e NaN, ma JSON non ha modo di rappresentarli, e i due linguaggi gestiscono la cosa in modo diverso:
JSON.stringify(JSON5.parse('{a: Infinity, b: NaN}'));
// '{"a":null,"b":null}' (diventa null senza alcun avviso)
json.dumps(json5.loads('{a: Infinity, b: NaN}'))
# '{"a": Infinity, "b": NaN}' (un output che non è JSON valido)
json.dumps(json5.loads('{a: Infinity}'), allow_nan=False)
# ValueError: Out of range float values are not JSON compliant: inf
Se un file JSON5 può contenerli, in Python passa allow_nan=False, oppure controllali prima di convertire. Quanto alle stringhe JSON5 tra apici singoli che contengono " o backslash, JSON.stringify ne rifà l’escape. Le regole sono nella guida all’escape delle stringhe JSON.
Validazione del JSON convertito
Dopo la conversione, incolla l’output nel Formattatore JSON per validarlo e formattarlo con indentazione. Funziona direttamente nel browser.
Tieni presente che il formattatore accetta solo JSON stretto. Analizza il testo con il JSON.parse del browser, quindi un file JSONC o JSON5 incollato così com’è fallisce con un errore di sintassi, che indica la riga e la colonna in cui il parsing si è fermato. Prima converti, poi valida.
Quando non usare JSONC o JSON5
- Payload delle API e scambio di dati. RFC 8259 dice che un generatore JSON “MUST strictly conform to the JSON grammar” (deve rispettare rigorosamente la grammatica JSON). Dall’altra parte di solito c’è
JSON.parseojson.loads, ed entrambi rifiutano i commenti. package.json. npm richiede JSON stretto. Basta un solo commento perché comandi npm comenpm runfalliscano conEJSONPARSE.- File letti da strumenti che non controlli.
require('./tsconfig.json')di Node usa il parser JSON stretto e fallisce su un tsconfig con commenti (SyntaxError: …tsconfig.json: Expected property name or '}' in JSON at position 4). Qualsiasi script che legge un file JSONC ha bisogno di un parser JSONC. - Un file
.jsondiventato JSONC senza che nessuno se ne accorgesse. La documentazione di Renovate consiglia un file.jsoncinvece di un.jsoncon commenti, perché quest’ultimo “can cause issues with editors and syntax highlighting” (può creare problemi con gli editor e con l’evidenziazione della sintassi). Un’estensione esplicita dice a ogni strumento cosa aspettarsi.
Se stai scegliendo da zero un formato di configurazione e vuoi i commenti ovunque, TOML e YAML li supportano nativamente. Vedi TOML vs JSON vs YAML.
File di configurazione del mondo reale
JSON5 e JSONC sono già ampiamente usati in file di configurazione che incontri ogni giorno. Ecco esempi concreti:
TypeScript (tsconfig.json — JSONC)
{
// La modalità strict cattura più bug a tempo di compilazione
"compilerOptions": {
"strict": true,
"target": "ES2022",
"module": "ESNext",
"outDir": "./dist",
// Alias di percorso per import più puliti
"paths": {
"@/*": ["./src/*"],
"@tests/*": ["./tests/*"],
},
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"],
}
tsconfig.json di TypeScript usa JSONC nativamente — commenti e virgole finali funzionano fuori dalla scatola. È uno dei file JSONC più comuni in qualsiasi progetto JavaScript/TypeScript.
Babel (babel.config.json — JSON5)
Babel analizza babel.config.json e .babelrc.json come JSON5, quindi lì funzionano anche chiavi senza virgolette e apici singoli.
{
// Apici singoli e chiavi senza virgolette lo rendono più leggibile
presets: [
['@babel/preset-env', {
targets: '> 0.25%, not dead',
modules: false, // Lascia che il bundler gestisca i moduli
}],
],
plugins: [
'@babel/plugin-transform-runtime',
],
}
Impostazioni workspace di VS Code (.vscode/settings.json — JSONC)
{
// Preferenze editor
"editor.fontSize": 14,
"editor.tabSize": 2,
"editor.formatOnSave": true,
// Override specifici per linguaggio
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
},
}
Suggerimenti pratici e avvertenze
1. Converti prima della produzione
Il JSON.parse dei browser accetta solo JSON stretto. Converti i file in fase di build, come mostrato nella sezione sulla conversione qui sopra.
2. Sicurezza e affidabilità
La permissività può nascondere campi indesiderati. Valida sempre la configurazione con JSON Schema o zod prima di consumarla:
// Valida la forma della config con zod dopo il parsing
import { readFileSync } from 'node:fs';
import { z } from 'zod';
import JSON5 from 'json5';
const ConfigSchema = z.object({
port: z.number().min(1).max(65535),
host: z.string(),
debug: z.boolean().default(false),
});
const raw = JSON5.parse(readFileSync('config.json5', 'utf8'));
const config = ConfigSchema.parse(raw); // Lancia se non valido
3. Convenzioni di team
- Dichiara nel README che
*.json5è solo per le config; i pacchetti rilasciati dovrebbero spedire.jsonstretto. - Standardizza le regole di Prettier per evitare diff rumorosi.
- Usa
.editorconfigper imporre indentazione coerente tra file JSON, JSON5 e JSONC.
4. Prestazioni
Analizzare JSON5/JSONC aggiunge dipendenze e leggero overhead — va bene per CLI e dev tooling, ma misura per la produzione. Per file di configurazione caricati una volta all’avvio, è trascurabile. Per percorsi caldi che analizzano migliaia di oggetti al secondo, attieniti al JSON stretto.
Domande frequenti
Qual è la differenza tra JSON5 e JSONC?
JSONC è JSON standard più i commenti // e /* */; il supporto per le virgole finali dipende dal parser. JSON5 va oltre con la sintassi di ES5.1: chiavi senza virgolette, apici singoli, numeri esadecimali, Infinity/NaN e virgole finali. Un file JSONC valido di solito è anche JSON5 valido, ma non vale il contrario. Scegli JSONC per file di config dove i commenti bastano; scegli JSON5 quando hai bisogno di sintassi più ricca.
Posso usare JSON5 o JSONC nelle API di produzione?
No — JSON5 e JSONC sono progettati per file di configurazione, non per scambio dati. Le API dovrebbero usare JSON standard (RFC 8259) per la massima interoperabilità. Riserva JSON5/JSONC per file di config locali come tsconfig.json, .vscode/settings.json o configurazione di ambiente dove la leggibilità umana conta più del parsing macchina.
VS Code supporta JSON5 nativamente?
Non di serie. L’estensione JSON integrata in VS Code registra linguaggi come json, jsonc e jsonl, ma non json5, quindi per avere l’evidenziazione della sintassi nei file .json5 serve un’estensione del marketplace. JSONC invece è integrato: le impostazioni, tasks.json, launch.json e tsconfig.json si aprono tutti in modalità JSON with Comments.
Come converto JSON5 in JSON standard?
Usa il pacchetto npm json5: JSON5.parse() legge JSON5, poi JSON.stringify() produce JSON standard. Per uso CLI, esegui npx json5 < input.json5 > output.json. I commenti vengono eliminati, e JSON.stringify trasforma Infinity e NaN in null. Strumenti online come il nostro JSON Formatter possono anche validare l’output convertito per assicurare la correttezza.
JSONC è la stessa cosa di JSON con commenti?
Sì — “JSON with Comments” è il nome della modalità linguaggio di VS Code, e jsonc è il suo ID di linguaggio e la sua estensione di file. Non esiste uno standard formale: su jsonc.org c’è una bozza della community, basata su ciò che jsonc-parser accetta con le opzioni predefinite. Al JSON standard aggiunge i commenti // e /* */, mentre il supporto per le virgole finali dipende dal parser. I parser rimuovono i commenti prima dell’elaborazione, quindi la struttura dati risultante è identica al JSON standard.
Per più strumenti per sviluppatori basati su browser inclusi codifica Base64, generazione di hash e conversione di timestamp, vedi la nostra Guida agli strumenti essenziali per sviluppatori.
Riepilogo
Bilanciare leggibilità e rigore è una classica lotta degli sviluppatori. JSON5 e JSONC migliorano l’esperienza di scrittura, e con la giusta pipeline di build e validazione, puoi godere dei vantaggi del “JSON permissivo” in sicurezza.
Riferimenti
- Formato di interscambio dati JSON5 1.0.0
- VS Code: JSON with Comments
- TypeScript: cos’è un tsconfig.json
- RFC 8259: il formato di interscambio dati JavaScript Object Notation (JSON)
- Specifica JSONC (bozza della community)
- jsonc-parser
- Babel: file di configurazione
- Riferimento dei metadati Dev Container