YAML vs JSON vs TOML : choisir un format de configuration
Pourquoi le choix du format de configuration est VRAIMENT important
Choisis le mauvais format de configuration, et tu passeras des heures à déboguer une virgule manquante. Tu te battras avec un analyseur qui supprime une clé en silence. Tu devras expliquer les règles d'indentation obscures à un nouveau membre de l'équipe, encore une fois. Ce ne sont pas des hypothèses. Ce sont ces petites coupures qui vident les projets de leur sang, semaine après semaine. Dans les logiciels modernes, tu tomberas presque toujours sur du YAML, du JSON ou du TOML. Docker Compose utilise YAML. Les API REST parlent très majoritairement en JSON. Le gestionnaire de paquets Cargo de Rust a choisi TOML. Chacun de ces choix reflète un compromis délibéré entre la lisibilité pour un humain, l'analyse par une machine et la puissance d'expression. La différence entre un projet maintenable et un projet fragile se résume souvent à la compréhension de ces compromis, au lieu de simplement copier le format utilisé dans le premier tutoriel venu. Nous allons comparer les trois selon les critères qui comptent vraiment : la syntaxe, les types de données, les commentaires, les chaînes de caractères multilignes et l'outillage. On verra aussi pourquoi tu pourrais vouloir les convertir entre eux et, plus important encore, les vraies limites de ce processus de conversion. Mieux vaut les connaître avant de commencer.
JSON : strict, portable et étonnamment pénible à écrire à la main
Le JSON, ou JavaScript Object Notation, a une caractéristique principale : sa rigueur. Il a été standardisé sous la norme RFC 8259 en 2017, mais son âme vient de la spécification originale de Douglas Crockford au début des années 2000. Il n'y a qu'une seule et unique façon d'écrire une structure de données donnée. Les clés exigent des guillemets doubles. Les virgules en fin de ligne sont interdites. Et les commentaires ? Ils n'existent pas. Pas dans la spécification, en tout cas. Dans la communication de machine à machine, cette rigidité est une qualité, pas un défaut. La prévisibilité du JSON est la raison pour laquelle il a conquis le monde des API REST et des outils de build. Chaque langage majeur a un analyseur dans sa bibliothèque standard, et comme le format est si peu ambigu, tu peux être sûr que ce que tu envoies est ce qu'ils recevront. Ça marche, tout simplement. La douleur arrive dès qu'un humain doit en écrire. Quiconque a passé dix minutes à chercher une virgule manquante dans un `webpack.config.js` géant connaît ce sentiment. Un simple bloc de connexion à une base de données, ça va : ```json { "database": { "host": "localhost", "port": 5432, "name": "myapp_production" } } ``` Mais fais-le passer à 40 clés, imbrique-le sur trois niveaux, et oublie une seule virgule... L'analyseur abandonne souvent, te renvoyant à la fin du fichier avec une erreur cryptique au lieu de pointer la ligne du problème. L'absence de commentaires est tout aussi frustrante. Les gens ont recours à des bidouilles comme `"_comment": "ce paramètre contrôle le TTL du cache"`, polluant le modèle de données juste pour se laisser une note pour le futur. C'est pourquoi des formats comme JSON5 et JSONC (JSON avec commentaires) existent. Ils sont populaires — le `settings.json` de VS Code utilise JSONC — mais ils ne sont fondamentalement pas standards. Ne te laisse pas abuser en pensant qu'ils sont une option sûre par défaut. Si tu envoies un fichier JSONC à un analyseur standard, il va planter.
YAML : lisibilité maximale, pièges maximaux
YAML, qui signifie YAML Ain't Markup Language (YAML n'est pas un langage de balisage), met la lisibilité humaine au premier plan. Il se débarrasse des accolades et des guillemets du JSON au profit d'une structure propre, basée sur l'indentation. Il a des commentaires natifs (`#`) et gère les chaînes multilignes avec élégance. Un workflow GitHub Actions ou un manifeste Kubernetes écrit en YAML est indéniablement plus facile à parcourir pour un humain que son équivalent JSON. Voici à quoi ressemble cette même configuration de base de données en YAML : ```yaml database: host: localhost port: 5432 name: myapp_production # jeu de réplicas ajouté le 10/03/2024 replicas: - replica1.internal - replica2.internal ``` C'est plus propre, et le commentaire crucial qui explique le changement est un citoyen de première classe. Les chaînes multilignes sont aussi un problème résolu grâce aux scalaires de bloc — les caractères `|` et `>` — ce qui permet d'intégrer des requêtes SQL ou des scripts shell dans une configuration sans que ça ne devienne un fouillis illisible. Mais cette lisibilité a un prix, et on le paie en ambiguïté et en dangers cachés. Ce sont les fameux 'footguns' (pièges) du YAML. Le plus célèbre est le 'problème du drapeau norvégien', où le code pays `NO` est interprété par défaut comme le booléen `false` dans les anciennes versions de YAML (que de nombreux outils utilisent encore !). Un seul espace mal placé dans l'indentation ne génère pas d'erreur ; il modifie silencieusement toute la structure de tes données. La spécification elle-même est un monstre de 86 pages — plus longue que la spec de HTTP/1.1 ! — ce qui te donne une idée de la complexité qui se cache sous cette surface apparemment simple. Alors, qu'est-ce qu'on en conclut ? Pour l'infrastructure-as-code et les pipelines CI/CD, où les fichiers de configuration sont écrits et relus par des humains toute la journée, la lisibilité du YAML vaut souvent le risque. Mais pour les configurations générées par du code et rarement touchées à la main, cet avantage s'évapore, et tu te retrouves avec un pistolet chargé pointé sur ton pied.
TOML : le juste milieu pragmatique
TOML, ou Tom's Obvious, Minimal Language, est le choix pragmatique. Créé par le cofondateur de GitHub, Tom Preston-Werner, et finalisé en version 1.0.0 en 2021, sa seule raison d'être est de proposer un format de configuration évident et sans ambiguïté qui reste agréable à lire. Il ressemble un peu à un fichier INI à l'ancienne, avec des en-têtes de section entre crochets, mais il ajoute des types de données explicites, ce qui est sa fonctionnalité phare. Cette structure encourage une configuration plus plate, ce qui peut être une contrainte saine. ```toml [database] host = "localhost" port = 5432 name = "myapp_production" # jeu de réplicas ajouté le 10/03/2024 replicas = ["replica1.internal", "replica2.internal"] ``` C'est là que TOML répond directement aux plus gros problèmes de YAML. Il n'y a pas de chaînes de caractères nues et ambiguës. `port = 5432` est un entier. `enabled = true` est un booléen. `NO` est juste la chaîne de caractères 'NO'. Tu n'as jamais à t'inquiéter qu'une valeur soit magiquement transformée en quelque chose que tu n'avais pas prévu. Il prend également en charge nativement les dates et heures, y compris les timestamps RFC 3339, ce qui est un énorme soulagement pour quiconque a déjà dû manipuler des chaînes de date. Sa principale faiblesse est la représentation de données profondément imbriquées ou très répétitives. La syntaxe `[[section]]` pour un tableau de tables fonctionne pour des cas simples, comme les entrées `[[bin]]` de Cargo, mais elle devient vite lourde. Si tu as besoin de trois ou quatre niveaux d'imbrication, le modèle d'indentation de YAML devient soudainement beaucoup plus attrayant. TOML omet aussi délibérément des fonctionnalités comme les ancres et les alias de YAML, donc si tu as besoin de réduire la duplication entre les environnements, c'est raté. Les gros fichiers TOML peuvent devenir très répétitifs. Son adoption est solide mais pas universelle. Python a ajouté `tomllib` à sa bibliothèque standard en version 3.11, un gage de confiance majeur. Avant ça, il fallait aller chercher un paquet tiers. Si ton équipe est plongée dans les écosystèmes Rust, Python moderne ou Go, TOML est un excellent choix, très confortable. Pour les projets qui s'étendent sur de nombreux langages différents, tu voudras d'abord vérifier la disponibilité des analyseurs avant de t'engager.
Face-à-face : tableau comparatif des fonctionnalités
Mettons tous les compromis au même endroit. Voici une comparaison directe des fonctionnalités qui causent le plus de maux de tête dans les fichiers de configuration du monde réel. **Commentaires :** YAML & TOML : Oui, via les commentaires de ligne avec `#`. JSON : Non. Pas dans la spec, et jamais. Fais avec. **Virgules en fin de ligne :** YAML & TOML : Non applicable, car ils n'utilisent pas de virgules comme délimiteurs principaux. JSON : Interdit. Une source classique de `git diff` frustrants et d'erreurs d'analyse. **Chaînes multilignes :** YAML : Excellent support via les scalaires de bloc (`|`, `>`), bien que les indicateurs de rognage (`-`, `+`) puissent être délicats. TOML : Bon support avec les chaînes de caractères entre triples guillemets. JSON : Horrible. Tu es coincé à ajouter manuellement des échappements `\n`. C'est moche et source d'erreurs. **Types date et heure :** TOML : Oui, des objets date/heure de première classe. YAML : Oui, dans la version 1.2, mais le support des analyseurs peut être incohérent. JSON : Non. Les dates ne sont que des chaînes de caractères par convention, et c'est à toi de les analyser. **Ancres et alias (configs DRY) :** YAML : Oui, avec `&anchor` et `*alias`. Une fonctionnalité puissante mais souvent déroutante pour réduire la répétition. TOML & JSON : Non. Soit tu te répètes, soit tu comptes sur une étape de pré-traitement. **Validation de schéma :** JSON : Oui, avec JSON Schema, un standard mature et largement supporté. YAML : Peut utiliser JSON Schema, mais nécessite un outillage spécifique (`ajv`, `yamale`). TOML : L'outillage est beaucoup moins mature sur ce point. C'est un point faible évident. **Taille de fichier pour des données équivalentes :** JSON est le plus compact une fois minifié. Pour les fichiers lisibles par un humain, YAML et TOML sont comparables. La différence est rarement supérieure à 10-15 % pour une configuration typique, ce n'est donc pas un facteur de décision majeur. **Vitesse d'analyse :** Pour lire une configuration au démarrage d'une application, tous sont largement assez rapides. Pour la sérialisation à haut débit (des milliers d'opérations/seconde), JSON est le champion incontesté, grâce à des bibliothèques hautement optimisées comme `simdjson`.
Convertir entre les formats : ce qui marche et ce qui ne marche pas
Tôt ou tard, tu auras besoin de convertir des fichiers entre ces formats. Peut-être que tu migres un projet, que tu génères une configuration YAML à partir d'une API JSON, ou que tu donnes un fichier TOML à un vieil outil qui ne parle que JSON. Ça arrive. CocoConvert peut se charger du travail mécanique pour toi avec ses convertisseurs JSON vers YAML, YAML vers JSON, TOML vers JSON et JSON vers TOML. Pour des configurations simples avec des types de données basiques, la conversion est rapide et sans perte. Il te suffit de téléverser ton fichier sur la page de Conversion, de choisir ton format cible, et c'est parti. Mais la conversion automatisée a des limites strictes. Tu dois être conscient de ce qui se perd dans la traduction, car ce n'est pas un bug de l'outil — c'est une incompatibilité fondamentale entre les formats. **Les commentaires sont perdus lors de la conversion vers JSON.** JSON n'a aucune notion de commentaires. Point final. Quand tu convertis un fichier YAML ou TOML commenté en JSON, ces commentaires disparaissent à jamais. Il n'y a pas de solution de contournement ; c'est une limitation de la spécification JSON elle-même. **Les ancres YAML sont développées, pas préservées.** Si ton fichier YAML utilise `&defaults` et `*defaults` pour rester DRY, cette structure sera perdue. Le convertisseur développera les ancres, ce qui signifie que les données en sortie seront identiques, mais dupliquées partout. Le fichier résultant fonctionnera, mais il ne sera pas aussi facile à maintenir. **Les dates/heures TOML peuvent devenir des chaînes de caractères.** Le format natif de TOML `created_at = 2024-01-15T09:30:00Z` n'a pas d'équivalent direct en JSON. CocoConvert le transformera en une chaîne ISO 8601 standard, ce qui est la convention correcte. Mais l'application qui lit ce JSON doit être assez intelligente pour savoir qu'elle doit ré-analyser cette chaîne pour en faire un objet date. **La conversion de TOML profondément imbriqué vers YAML** fonctionne bien structurellement, mais le résultat peut être surprenant. La syntaxe `[[array of tables]]` de TOML correspond à une séquence de mappages en YAML, ce qui peut paraître étrange si tu n'as pas l'habitude de le voir. Toujours vérifier le résultat de la conversion avant de lui faire confiance en production. Un `diff` rapide sur un fichier que tu as converti dans un sens puis dans l'autre (un aller-retour) est le meilleur moyen de déceler les surprises.
Prendre la décision : quel format pour quelle situation
Il n'y a pas de réponse unique, mais ne te laisse pas berner en pensant que le choix n'a pas d'importance. Des heuristiques claires ont émergé pour savoir quand utiliser chaque format. **Utilise JSON quand :** la configuration est pour les machines, pas pour les gens. Si elle est générée et consommée par des outils, et que les humains ne la modifieront que rarement à la main, la rigueur de JSON est une vertu. C'est pourquoi `package.json` et `tsconfig.json` sont en JSON. L'objectif est la compatibilité maximale. **Utilise YAML quand :** les humains sont le public principal. Pour les manifestes Kubernetes, les GitHub Actions ou les playbooks Ansible, la lisibilité est primordiale. La configuration est écrite et relue constamment par des gens. Oui, les pièges sont réels, mais ils sont gérables. Ma seule recommandation non négociable : si tu utilises YAML, tu *dois* imposer un linter comme `yamllint` dans ton pipeline de CI. Sans exception. **Utilise TOML quand :** tu veux la lisibilité de YAML sans son ambiguïté dangereuse. Si ta configuration est majoritairement plate et que ton équipe travaille dans un écosystème avec un bon support (comme Rust avec Cargo.toml ou Python moderne avec pyproject.toml), TOML est un choix fantastique. C'est aussi le format le plus sympathique à modifier pour les utilisateurs finaux de ton application, car la syntaxe est simple et les erreurs de l'analyseur sont généralement utiles. **Quand aucun des trois ne convient parfaitement :** Prends du recul et demande-toi si un fichier de configuration statique est même le bon outil. De simples paires clé-valeur peuvent souvent vivre dans des variables d'environnement. Pour des scénarios vraiment complexes avec de la logique conditionnelle, essayer de tout faire rentrer au chausse-pied dans du YAML ou du TOML est une erreur. Tu es passé à autre chose. Il est temps d'admettre que tu as besoin d'un vrai langage de programmation pour ta configuration, que ce soit un langage de configuration dédié comme Dhall ou Starlark, ou juste un simple script Python. C'est un plus grand engagement, mais c'est mieux que de construire un monstre à partir de YAML imbriqué. Si tu te retrouves coincé du mauvais côté d'une de ces décisions en plein milieu d'un projet, CocoConvert peut gérer la migration. Le choix stratégique du format qui servira le mieux ton équipe, cependant, ne dépend que de toi.