JSON5 et JSONC : du JSON avec des commentaires
L’essentiel : Les deux dialectes existent parce qu'une configuration écrite par des humains a besoin de commentaires et de virgules finales, mais leur syntaxe et leur portée écosystémique diffèrent, et un mauvais choix bloque votre chaîne d'outils.

L'essentiel : utilisez JSONC pour les commentaires dans la configuration VS Code et TypeScript, utilisez JSON5 lorsque vous avez besoin de la syntaxe de littéraux ES5.1 élargie comme les guillemets simples ou les clés non citées, et gardez les API publiques en JSON standard.
JSON standard n'autorise pas les commentaires, alors chaque équipe en écrit discrètement — jusqu'au jour où la compilation casse. Plutôt que de le faire en cachette, choisissez un dialecte approprié.
1. Deux dialectes aux motivations différentes
- JSONC (JSON with Comments) : JSON standard plus commentaires et virgules finales, avec presque aucune autre modification de syntaxe. C'est le standard de fait de l'écosystème VS Code —
settings.json,tsconfig.jsonet.eslintrc.jsonl'utilisent tous. - JSON5 : bien plus ambitieux, aligné directement sur le littéral d'objet ES5.1 — guillemets simples, clés non citées, hexadécimal,
Infinity/NaN, continuation de ligne par antislash et signes+initiaux.
Une phrase pour les distinguer : JSONC rend seulement l'écriture confortable ; JSON5 permet d'écrire un fichier de configuration comme s'il s'agissait de JavaScript.
2. Tableau comparatif des syntaxes
| Fonctionnalité | JSON standard | JSONC | JSON5 |
|---|---|---|---|
Commentaires // /* */ |
✗ | ✓ | ✓ |
| Virgules finales | ✗ | ✓ | ✓ |
| Chaînes entre guillemets simples | ✗ | ✗ | ✓ |
| Clés non citées | ✗ | ✗ | ✓ |
| Nombres hexadécimaux | ✗ | ✗ | ✓ |
Point décimal initial/final .5 5. |
✗ | ✗ | ✓ |
Nombres commençant par + |
✗ | ✗ | ✓ |
Infinity / NaN |
✗ | ✗ | ✓ |
Continuation de fin de ligne \ |
✗ | ✗ | ✓ |
| Chaînes multilignes | ✗ | ✗ | ✓ (réalisées par continuation) |
| Valeur racine quelconque | ✓ | ✓ | ✓ |
La spécification complète de JSON5 dépasse à peine une page ; le paquet json5 est maintenu par la communauté depuis longtemps, et navigateurs comme Node se comportent à l'identique.
3. Analyse : deux API, deux types de capacité de positionnement
3.1 JSON5 : analyse simple du document entier
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 renvoie un objet simple sans information de décalage — parce qu'il ne vise pas les scénarios d'édition, seulement la « lecture de configuration ».
3.2 JSONC : un arbre syntaxique avec décalages
La valeur de jsonc-parser ne réside pas dans l'analyse mais dans l'édition. Il offre trois couches d'API :
| API | Objectif | Usage typique |
|---|---|---|
parse |
Analyser en un arbre portant offset/length |
Coloration syntaxique, pliage, navigation |
visit |
Parcours en profondeur ; le rappel reçoit le chemin du nœud | Inspection à la manière de JSONPath |
modify + applyEdits |
Produire une édition de texte minimale, puis l'appliquer au texte d'origine | Modifier une valeur en conservant les commentaires |
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));
La sortie conserve les commentaires d'origine et ne remplace que les trois caractères de 8080 :
{
// port configuration
"server": {
"port": 3000 // 80 in production
}
}
C'est exactement ce que « modifier une configuration avec des expressions régulières » ne sait pas faire : une expression régulière ne sait pas quel 8080 modifier, ni que le 8080 à l'intérieur d'une chaîne doit rester intact.
3.3 Les messages d'erreur doivent porter des décalages
Les codes d'erreur de jsonc-parser sont des valeurs d'énumération ; les plus courants sont :
| Code d'erreur | Signification |
|---|---|
InvalidSymbol |
Un caractère qui ne devrait pas être là est apparu |
PropertyNameExpected |
Un nom de clé était attendu |
ColonExpected |
Un deux-points était attendu |
CommaExpected |
Une virgule était attendue |
CloseBraceExpected |
L'objet n'a pas été fermé |
UnexpectedEndOfComment |
Le commentaire n'a pas été fermé |
InvalidEscapeCharacter |
Échappement invalide |
Une fois offset converti en ligne et colonne, l'éditeur peut tracer le soulignement exactement sur la position fautive.
4. Quand utiliser lequel
| Scénario | Recommandation | Raison |
|---|---|---|
| Corps de requêtes/réponses d'API publiques | JSON standard | Les dialectes ne sont pas pris en charge par les clients génériques |
package.json, composer.json |
JSON standard | Les gestionnaires de paquets ne comprennent que le JSON standard |
tsconfig.json, .vscode/settings.json |
JSONC | Valeur par défaut de l'écosystème, pris en charge nativement par la chaîne d'outils |
| Configuration d'application (nécessite des commentaires) | JSONC ou YAML | Les commentaires doivent survivre pendant que les outils peuvent encore lire et écrire |
Besoin de Infinity, d'hexadécimal ou de littéraux complexes |
JSON5 | La puissance d'expression la plus forte |
| Échange de données, journaux, caches | Lignes délimitées ou JSON standard | Le flux continu et l'universalité sont requis |
Règle empirique : si le fichier doit être lu par un « outil non humain », privilégiez le JSON standard ; n'envisagez un dialecte que lorsque vous êtes certain qu'il est lu uniquement par votre propre code.
5. Trois sortes de risques introduits par les dialectes
5.1 Débordement du besoin
Quand un autre outil lit un fichier de configuration JSON5 et appelle JSON.parse, il plante purement et simplement. Le symptôme typique est « ça marche en local, ça échoue sur Docker » — parce que le conteneur suit un autre chemin de lecture.
Contre-mesure : ajoutez une vérification en CI dans le dépôt qui liste explicitement les fichiers autorisés à utiliser un dialecte ; tout le reste est validé comme du JSON standard.
5.2 Surprises autour de l'inférence de types
JSON5 autorise les clés non citées et les guillemets simples, mais ne permet pas d'introduire des constructions littérales comme des dates ou des expressions régulières — c'est toujours un format de données, pas une évaluation JavaScript.
Certains ont cru que JSON5 pouvait exprimer new Date(), pour voir l'analyse échouer. JSON5 n'est pas eval.
5.3 Commentaires supprimés sans bruit
Ni JSON5.stringify ni JSON.stringify ne préservent les commentaires. Ainsi, « lire, ajuster une valeur, réécrire » perd tous les commentaires.
Lorsque les commentaires doivent survivre, les seules options sont l'API d'édition de jsonc-parser, ou une bibliothèque YAML qui préserve les commentaires.
6. Recommandations pratiques
- [ ] Tenez un tableau « type de fichier → format » dans la documentation d'équipe, pour que personne n'improvise ;
- [ ] Enveloppez la lecture de configuration dans un unique
loadConfig()qui décide en interne quel analyseur utiliser, afin que le code métier n'appelle jamaisJSON.parsedirectement ; - [ ] Lors d'une modification programmatique d'une configuration commentée, utilisez
modify+applyEdits; ne réécrivez jamais tout le fichier ; - [ ] Validez aussi les fichiers dialectaux en CI (
jsonc-parserpour JSONC,JSON5.parsepour JSON5), sinon les erreurs de syntaxe n'apparaissent qu'à l'exécution ; - [ ] Utilisez du JSON standard pour les interfaces publiques, les clés de cache et les charges utiles de files de messages.
FAQ
Comment choisir entre JSON5 et JSONC ?
Choisissez en fonction de l'exécution plutôt que du nombre de syntaxes : VS Code, TypeScript et ESLint lisent JSONC par défaut, si bien que JSONC offre la meilleure compatibilité ; ne recourez à JSON5 que si vous avez besoin de la syntaxe de littéraux ES5.1 élargie, comme les guillemets simples, les clés non citées ou Infinity. Aucun des deux dialectes ne convient aux réponses d'API publiques.
Pourquoi un analyseur JSON standard ne peut-il pas lire JSONC directement ?
JSONC autorise les commentaires et les virgules finales, alors que JSON.parse n'accepte que le JSON de la RFC 8259 et lève une erreur sur l'un comme sur l'autre. Lire du JSONC exige un analyseur tel que jsonc-parser, ou retirer les commentaires avant de confier le texte à un analyseur standard.
Les commentaires d'un fichier JSONC doivent-ils survivre aux modifications ?
Oui, mais uniquement via une API d'édition. modify et applyEdits de jsonc-parser modifient le nœud visé tout en préservant les autres commentaires ; analyser en objet puis sérialiser supprime tous les commentaires.