Skip to content
Retour au blog
Tutoriels

Le problème Norway de YAML et les différences JSON-YAML

Pourquoi YAML lit « no » comme false. Pannes K8s réelles dues aux guillemets de chaînes. Choix JSON vs YAML, règles d'indentation et conversions de manifestes K8s expliqués.

14 min de lecture

Le problème Norway de YAML et les différences JSON ↔ YAML que les ingénieurs doivent connaître

C’était un déploiement Helm de routine. L’équipe avait passé deux jours à peaufiner un fichier values.yaml pour un déploiement multi-région. Le chart créait un ConfigMap Kubernetes avec des métadonnées de locale — y compris le code pays pour leur centre de données norvégien. Quelqu’un a tapé country: NO et l’a validé. Le pipeline CI est passé au vert. Le déploiement s’est effectué.

Puis les alertes sont arrivées.

Le ConfigMap contenait country: false au lieu de country: "NO". Chaque service en aval qui lisait le champ pays obtenait un booléen au lieu d’une chaîne. La comparaison de chaînes échouait. La logique de routage tombait sur une valeur par défaut. Le trafic qui aurait dû rester en Norvège se retrouvait traité par le mauvais point de terminaison régional.

La cause racine était une seule chaîne non mise entre guillemets dans un fichier YAML. YAML 1.1 — la version qu’utilisent pratiquement tous les outils Kubernetes — traite NO comme un booléen false. Il traite YES, ON, OFF, Y, N, no, yes, on, off, y, n et une douzaine d’autres variantes de la même façon. Aucun avertissement. Aucune erreur. Silencieusement faux.

JSON n’a pas ce problème. {"country": "NO"} est toujours une chaîne. La coercition implicite de type de YAML est à la fois sa plus grande commodité et son piège le plus dangereux.

Ce guide couvre le tableau complet : pourquoi le problème Norway existe, ce qui a changé dans YAML 1.2 (et pourquoi la plupart des outils l’ignorent), comment écrire des stratégies de guillemets correctes, les règles d’indentation qui piègent les débutants, les pièges de précision numérique et quatre scénarios de conversion du monde réel, des manifestes Kubernetes aux plans Terraform. Lorsque vous avez besoin d’aplatir en toute sécurité une valeur JSON en YAML sans ce piège, notre convertisseur JSON vers YAML met automatiquement entre guillemets les chaînes problématiques Norway.

JSON vs YAML — Quand utiliser lequel

Avant de plonger dans le problème Norway, il est utile de comprendre pour quoi chaque format est réellement optimisé. Ils ne sont pas interchangeables — chacun a un centre de conception qui en fait le meilleur choix dans des contextes spécifiques.

DimensionJSONYAML
SyntaxeStricte — accolades, guillemets, virgules requisFlexible — basé sur l’indentation, ponctuation minimale
Système de typesExplicite : chaîne, nombre, booléen, null, tableau, objetImplicite — YAML 1.1 infère les types depuis la forme des valeurs
Lisibilité humaineAdapté aux développeurs, vérifiable par machineAdapté aux humains, facile à éditer à la main
Exigence de guillemetsChaînes toujours entre guillemetsLa plupart des scalaires peuvent être sans guillemets (source du problème Norway)
CommentairesNon supportésSupportés avec #
Utilisation principaleAPI, échange de données, systèmes de config modernesKubernetes, Docker Compose, Ansible, pipelines CI
Analyses surprenantesAucune — analyse stricteOui — Norway, octal, horodatages
Application de schémaÉcosystème JSON SchemaYAML Schema (moins d’outils)

JSON gagne quand vos données traversent des frontières de systèmes — API REST, files de messages, sérialisation de base de données. Les machines l’analysent, les machines le génèrent, et la syntaxe stricte rend la validation simple. Utilisez un Formateur JSON pour valider la structure avant l’envoi.

YAML gagne quand les humains sont les auteurs principaux. Les manifestes Kubernetes, les workflows GitHub Actions, les charts Helm, les playbooks Ansible — ce sont des fichiers que les développeurs lisent et modifient des dizaines de fois. La ponctuation réduite et le support des commentaires les rendent genuinement plus maintenables que leurs équivalents JSON.

Le problème survient à la frontière : quand un outil génère du JSON (comme kubectl get deploy -o json ou terraform show -json) et qu’un humain a besoin de versionner ou d’éditer le résultat comme du YAML. C’est cette conversion où vit le problème Norway. Notre convertisseur YAML vers JSON gère la direction inverse quand vous devez revenir en arrière.

Le problème Norway — Analyse approfondie

Le problème Norway n’est pas un bug. C’est une fonctionnalité de la spécification YAML 1.1 se comportant exactement comme prévu. Comprendre pourquoi il a été conçu ainsi — et pourquoi tant de systèmes implémentent encore la version 1.1 — est la clé pour l’éviter.

Pourquoi « no », « yes », « on », « off », « y », « n » sont mal analysés

La spécification YAML 1.1 définissait un type booléen large qui se voulait convivial pour les humains. Elle reconnaissait tous les éléments suivants comme true ou false :

Vrai : y, Y, yes, Yes, YES, true, True, TRUE, on, On, ON

Faux : n, N, no, No, NO, false, False, FALSE, off, Off, OFF

L’intention était bonne : les fichiers de configuration utilisent souvent yes/no au lieu de true/false en anglais, et YAML voulait supporter la façon naturelle dont les gens écrivent la configuration. Le problème est que yes, no, on, off, y et n sont aussi des valeurs de chaîne parfaitement légitimes qui signifient quelque chose d’entièrement différent dans la plupart des applications.

Voici l’incompatibilité en YAML concret :

# YAML 1.1 (ce que la plupart des analyseurs implémentent)
country: NO        # analysé comme : country: false   ← DANGER
enabled: yes       # analysé comme : enabled: true
restart: off       # analysé comme : restart: false
language: y        # analysé comme : language: true
shell: n           # analysé comme : shell: false

# Correct — les guillemets de chaîne explicites remplacent l'inférence de type
country: "NO"      # analysé comme : country: "NO"    ← sûr
enabled: "yes"     # analysé comme : enabled: "yes"
restart: "off"     # analysé comme : restart: "off"
language: "y"      # analysé comme : language: "y"
shell: "n"         # analysé comme : shell: "n"

Et la comparaison JSON :

{"country": "NO"}

En JSON, NO entre guillemets est toujours et inconditionnellement une chaîne. Il n’y a pas d’inférence implicite de type. La rigueur qui rend JSON verbeux est aussi ce qui le rend sûr.

Au-delà de la coercition booléenne, YAML 1.1 convertit aussi implicitement :

  • 123e4 → le nombre 1230000 (notation scientifique)
  • 0x1A → le nombre 26 (hexadécimal)
  • 0755 → le nombre 493 (octal — celui-ci casse les chaînes de permissions de fichiers Unix)
  • 2024-05-04 → un objet date dans de nombreux analyseurs (pas seulement une chaîne)
  • 1_000_000 → le nombre 1000000 (séparateur de soulignement)

Le problème Norway est vraiment juste le membre le plus célèbre d’une famille entière de coercitions implicites de types YAML.

YAML 1.1 vs 1.2 — Ce qui a changé

YAML 1.2 a été publié en 2009 — quatre ans après YAML 1.1. Son objectif principal était d’aligner strictement YAML avec JSON (puisque JSON est en fait un sous-ensemble valide de YAML 1.2) et de réduire les conversions implicites de types surprenantes.

Dans YAML 1.2 :

  • Les booléens sont réduits à exactement true et false (sensibles à la casse). C’est tout. yes, no, on, off sont des chaînes simples.
  • Les littéraux octaux nécessitent le préfixe 0o (0o755) — l’ancienne forme 0755 est une chaîne.
  • Les horodatages ne sont pas analysés implicitement — 2024-05-04 reste une chaîne sauf si vous le balisez explicitement.
  • La spécification elle-même est un sur-ensemble de JSON, ce qui signifie que tout document JSON valide est du YAML 1.2 valide.

Sur le papier, YAML 1.2 résout entièrement le problème Norway. En pratique, l’écosystème a à peine bougé.

BibliothèqueSpec par défautRisque Norway
PyYAML (Python)YAML 1.1Oui — yaml.safe_load analyse encore NO comme False
ruamel.yaml (Python)YAML 1.2 (optionnel)Configurable — plus sûr par défaut
js-yaml (Node.js)YAML 1.1Oui dans les anciennes versions ; les versions récentes ont l’option FAILSAFE_SCHEMA
eemeli/yaml (Node.js)YAML 1.2Non — 1.2 par défaut, ou version sélectionnable explicitement
gopkg.in/yaml.v2 (Go)YAML 1.1Oui
gopkg.in/yaml.v3 (Go)YAML 1.2Significativement plus sûr
Kubernetes / HelmYAML 1.1 (via Go yaml.v2)Oui — historique, très difficile à migrer
AnsibleYAML 1.1 (via PyYAML)Oui

La raison pour laquelle la migration est lente est la compatibilité ascendante. Les systèmes qui ont reposé sur l’analyse de yes/no comme booléens pendant une décennie ne peuvent pas changer silencieusement ce comportement sans casser les configurations existantes. Kubernetes en particulier est une base installée massive où changer la sémantique d’analyse YAML serait un changement radical à l’échelle du cluster.

La conclusion pratique : supposez la sémantique YAML 1.1 dans tout outil que vous n’avez pas explicitement configuré autrement. Mettez toujours entre guillemets les chaînes qui pourraient être mal lues comme des booléens, des horodatages ou des nombres.

Comment les systèmes de production sont touchés

Le code pays de la Norvège est l’exemple le plus cité car il est contre-intuitif — NO ressemble à une abréviation évidente, pas à un booléen. Mais le schéma se répète dans de nombreux scénarios du monde réel :

Codes d’aéroport IATA. L’aéroport norvégien de Harstad/Narvik a le code EVE. Sûr. Oslo Gardermoen est OSL. Aussi sûr. Mais toute application utilisant YAML pour stocker des codes d’aéroport régionaux est à un code de route no d’un booléen false en production.

Noms de variables d’environnement. ON est une valeur de variable d’environnement parfaitement valide signifiant « activé » dans certains systèmes hérités. OFF est son homologue. Migrer les configurations de scripts shell vers YAML sans mettre ces valeurs entre guillemets introduit une coercition silencieuse de types.

Champs utilisateur email. Un utilisateur dont le prénom ou le nom d’utilisateur est littéralement n, y ou l’un des mots déclencheurs se sérialisera incorrectement si l’application produit du YAML sans guillemets appropriés. C’est particulièrement insidieux car cela échoue uniquement pour un sous-ensemble d’utilisateurs.

Politiques de redémarrage Docker Compose. La valeur "no" du champ restart_policy signifie « ne pas redémarrer ». Si elle perd ses guillemets dans un aller-retour YAML, la valeur devient false, et Docker Compose peut l’interpréter comme « aucune politique de redémarrage spécifiée » ou générer une erreur de validation — dans les deux cas, le comportement de redémarrage du conteneur est erroné.

Champ shell: de GitHub Actions. Les valeurs de shell valides sont bash, pwsh, python, sh, cmd, powershell. Aucun d’eux n’est un mot Norway. Mais quelqu’un qui tape shell: yes ou shell: on comme espace réservé lors d’une édition de brouillon peut être surpris quand YAML le transforme en booléen avant même que le validateur ne le voie.

La correction dans tous les cas est la même : mettez entre guillemets les chaînes qui sont sémantiquement des chaînes, qu’un humain les reconnaisse ou non comme des mots-clés. Notre convertisseur JSON vers YAML applique cela automatiquement — toute valeur dans la liste des mots Norway est mise entre guillemets dans la sortie.

Stratégie de guillemets de chaînes

Une fois que vous comprenez pourquoi les mots Norway ne correspondent pas, la solution est de choisir la bonne stratégie de guillemets pour votre cas d’usage. YAML supporte trois modes, chacun avec des compromis différents.

Auto vs Double vs Simple

Les guillemets Auto (recommandés pour la plupart des conversions) laissent la bibliothèque décider quand les guillemets sont nécessaires. Les valeurs qui seraient mal lues sans guillemets — les mots Norway, les nombres, les horodatages, les chaînes qui ressemblent à de la syntaxe YAML — sont automatiquement mises entre guillemets. Tout le reste reste comme scalaire simple. Cela produit la sortie la plus lisible tout en restant sûre.

# Sortie en mode Auto
name: Alice          # simple — aucune ambiguïté
country: "NO"        # entre guillemets — mot Norway
age: 30              # simple — nombre sans ambiguïté
created: "2024-05-04" # entre guillemets — s'analyserait autrement comme une date
port: "8080"         # dépend de la bibliothèque — certaines mettent entre guillemets les chaînes d'apparence numérique

Les chaînes entre guillemets doubles encadrent toutes les valeurs de chaîne entre guillemets doubles. C’est explicite et auditable — tout lecteur peut voir que toutes ces valeurs sont des chaînes sans raisonner sur la spec. Le compromis est la verbosité et la lisibilité réduite pour les humains, surtout pour les configurations profondément imbriquées.

# Mode guillemets doubles
name: "Alice"
country: "NO"
replicas: "3"         # même les nombres deviennent des chaînes — peut causer des erreurs de schéma

Attention : si votre schéma cible attend un nombre et que vous le sérialisez comme une chaîne entre guillemets, l’analyseur YAML le typera correctement comme une chaîne, mais Kubernetes ou un autre consommateur strict peut rejeter le champ comme étant du mauvais type.

Les chaînes entre guillemets simples sont une fonctionnalité YAML uniquement — JSON n’a pas de syntaxe à guillemets simples. Les guillemets simples sont littéraux : pas de séquences d’échappement à l’intérieur. Le seul cas spécial est qu’un guillemet simple à l’intérieur d’une chaîne entre guillemets simples doit être doublé (''). Les guillemets simples sont idéaux pour les chaînes contenant des barres obliques inverses ou des caractères spéciaux qui nécessiteraient un échappement entre guillemets doubles.

# Mode guillemets simples
pattern: 'C:\Users\alice\Documents'  # pas d'échappement nécessaire
regex: '\d+\.\d+'                    # barres obliques inverses littérales

Pour les conversions JSON vers YAML destinées à revenir en JSON, préférez le mode Auto ou Double. Les chaînes entre guillemets simples introduisent une syntaxe spécifique à YAML qui nécessite un analyseur compatible YAML au retour.

Scalaires de bloc (| et >)

La syntaxe de scalaire de bloc de YAML est genuinement utile pour les chaînes multilignes — quelque chose que JSON gère maladroitement avec des séquences d’échappement \n.

Scalaire de bloc littéral | préserve exactement les sauts de ligne :

# Bloc littéral — sauts de ligne conservés
script: |
  #!/bin/bash
  set -euo pipefail
  echo "Starting deployment"
  kubectl apply -f manifest.yaml

# Représentation JSON équivalente (illisible)
# {"script": "#!/bin/bash\nset -euo pipefail\necho \"Starting deployment\"\nkubectl apply -f manifest.yaml\n"}

Scalaire de bloc replié > joint les lignes avec des espaces, transformant chaque saut de ligne en espace (sauf les lignes vides, qui deviennent des sauts de ligne) :

# Bloc replié — les sauts de ligne deviennent des espaces
description: >
  Ce service gère l'authentification
  pour toute la plateforme. Il supporte
  OAuth2, SAML et l'authentification par clé API.

# Résultat : "Ce service gère l'authentification pour toute la plateforme. Il supporte OAuth2, SAML et l'authentification par clé API.\n"

Les scalaires de bloc sont excellents pour intégrer des certificats TLS, des scripts shell multilignes ou des requêtes SQL dans des configurations YAML — des scénarios où l’équivalent JSON serait une longue ligne échappée qu’aucun humain ne peut lire.

Lors de la conversion de JSON vers YAML, la plupart des convertisseurs (y compris le nôtre) utilisent le mode Auto et représentent les chaînes multilignes avec des scalaires de bloc uniquement lorsqu’ils détectent des sauts de ligne intégrés. Les chaînes sur une seule ligne obtiennent des scalaires de flux (entre guillemets ou simples). Utilisez notre convertisseur JSON vers YAML pour voir la sortie avant de la valider dans un manifeste.

Indentation — 2 vs 4 espaces, tabulations interdites

Les règles d’indentation de YAML sont plus strictes qu’elles n’y paraissent. La spec a une règle absolue et une convention qui varie selon l’écosystème.

La règle absolue : les tabulations sont interdites. Chaque niveau d’indentation doit utiliser des espaces. Un caractère de tabulation dans un fichier YAML est une erreur d’analyse dans la plupart des analyseurs :

# INCORRECT — les tabulations causent des erreurs d'analyse
apiVersion: apps/v1
kind: Deployment
metadata:
	name: my-app     # ← caractère de tabulation ici → ParseError

# CORRECT — espaces uniquement
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app      # ← deux espaces

Le message d’erreur que vous verrez varie selon la bibliothèque. Dans PyYAML de Python :

yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token

Dans yaml.v3 de Go :

yaml: line 4: found character that cannot start any token

Configurez votre éditeur pour étendre les tabulations en espaces pour les fichiers YAML. Dans VS Code, ajoutez à vos paramètres d’espace de travail : "[yaml]": { "editor.insertSpaces": true, "editor.tabSize": 2 }.

La convention : 2 vs 4 espaces. Les deux sont valides. Les conventions de l’écosystème diffèrent :

ÉcosystèmeConventionRaison
Manifestes Kubernetes2 espacesLes docs et exemples officiels utilisent 2
Charts Helm2 espacesSuit la convention K8s
Docker Compose2 espacesExemples de la spec compose officielle
GitHub Actions2 espacesExemples de workflows officiels
Playbooks Ansible2 espacesDocumentation officielle
Configs traditionnelles4 espacesCorrespond au défaut de formatage JSON

Pour tout fichier qui sera consommé par Kubernetes ou Docker Compose, utilisez 2 espaces. Pour les fichiers de configuration autonomes qui ne seront lus que par des humains et des outils personnalisés, les deux fonctionnent — soyez simplement cohérent dans un fichier. Notre convertisseur JSON vers YAML est réglé par défaut sur 2 espaces et vous permet de passer à 4 pour les projets qui le préfèrent.

Une règle de plus : les éléments enfants doivent être indentés plus que leur parent, mais le nombre d’espaces supplémentaires peut être n’importe quel entier positif (1, 2, 3, 4…) — tant qu’il est cohérent dans un bloc. En pratique, utilisez toujours 2 ou 4 pour la lisibilité.

Gestion des nombres en JSON ↔ YAML

Les deux formats supportent les nombres, mais les cas limites diffèrent suffisamment pour causer des bugs en production.

Perte de précision pour les grands nombres

Le type Number de JavaScript est un float IEEE 754 64 bits. Il peut représenter exactement les entiers jusqu’à 2^53 − 1 = 9 007 199 254 740 991. Au-delà, la précision des entiers est perdue :

// Perte de précision JavaScript — ce n'est pas un problème YAML, mais cela affecte l'analyse JSON
JSON.parse('{"v": 9007199254740993}').v
// → 9007199254740992   (le 3 est devenu 2 — un bit perdu)

// Sûr — dans la plage 2^53
JSON.parse('{"v": 9007199254740991}').v
// → 9007199254740991   (exact)

Cela importe pour la conversion JSON vers YAML dans les environnements JavaScript car la précision est déjà perdue avant que la sérialisation YAML ne commence. Le champ metadata.resourceVersion de Kubernetes est un champ de chaîne spécifiquement parce que les versions de ressources peuvent dépasser la plage des entiers sûrs. D’autres champs qui semblent être de petits nombres — observedGeneration, composants de uid — sont plus sûrs, mais tout champ int64 dans une réponse K8s est potentiellement affecté.

Solutions :

  • Utilisez Python ou Go pour les pipelines de conversion impliquant de grands nombres — les deux gèrent nativement les entiers arbitraires.
  • Dans Node.js, utilisez un analyseur JSON qui supporte BigInt : JSON.parse(text, (_, v) => typeof v === 'number' && !Number.isSafeInteger(v) ? BigInt(v) : v).
  • Pour les champs qui doivent faire un aller-retour sans perte, sérialisez-les sous forme de chaînes à la source.
  • Lors de la révision du YAML converti, recherchez des champs comme resourceVersion, generation et les valeurs dérivées d’horodatages.

Particularités octales et hexadécimales

YAML 1.1 traite certaines chaînes de type nombre comme des entiers non décimaux :

# Surprises d'analyse YAML 1.1
permissions: 0755   # analysé comme octal 493, pas décimal 755
value: 0x1A         # analysé comme hex 26, pas chaîne "0x1A"

# Comportement YAML 1.2
permissions: 0755   # reste entier 755 (décimal) — l'octal nécessite le préfixe 0o
permissions: 0o755  # analysé comme octal 493 en 1.1 et 1.2

# Sûr pour les deux specs — mettez entre guillemets toute valeur avec zéro initial
permissions: "0755"  # toujours la chaîne "0755"

Le piège octal est particulièrement dangereux pour les permissions de fichiers Unix, les composants d’adresses IP avec des zéros initiaux (certains appareils réseau) et tout code numérique utilisant des zéros initiaux pour le remplissage (codes postaux, codes de produits). Mettez toujours ces valeurs entre guillemets lorsque vous écrivez du YAML à la main, ou assurez-vous que votre convertisseur les met entre guillemets — notre convertisseur JSON vers YAML détecte les chaînes numériques du JSON et préserve leur type de chaîne.

Conversions du monde réel

Le problème Norway et les stratégies de guillemets deviennent concrets lorsque vous les appliquez à de vrais scénarios de conversion.

Manifeste Kubernetes depuis JSON

Le flux de travail canonique : kubectl get deploy my-app -o json vous donne l’objet live en JSON. Vous souhaitez le nettoyer (supprimer status, creationTimestamp, les champs gérés) et le valider dans git comme manifeste YAML.

JSON source (abrégé) :

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "my-app",
    "namespace": "production",
    "labels": {
      "app": "my-app",
      "region": "NO"
    }
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": { "app": "my-app" }
    },
    "template": {
      "spec": {
        "containers": [{
          "name": "app",
          "image": "registry.example.com/my-app:v1.2.3",
          "env": [
            { "name": "REGION", "value": "NO" },
            { "name": "ENABLE_FEATURE", "value": "yes" }
          ]
        }]
      }
    }
  }
}

Sortie YAML attendue (avec protection Norway) :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
    region: "NO"          # entre guillemets — mot Norway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
        - name: app
          image: registry.example.com/my-app:v1.2.3
          env:
            - name: REGION
              value: "NO"           # entre guillemets — mot Norway
            - name: ENABLE_FEATURE
              value: "yes"          # entre guillemets — mot Norway

Notez que replicas: 3 est laissé sans guillemets — c’est un entier légitime que Kubernetes attend comme nombre. Les mots Norway dans les labels et valeurs env sont entre guillemets. Un convertisseur naïf qui ne gère pas les booléens YAML 1.1 produirait silencieusement region: false et value: false.

Après la conversion, validez avec : kubectl apply --dry-run=client -f manifest.yaml. Cela détecte les erreurs de schéma sans toucher le cluster.

Essayez la conversion dans notre convertisseur JSON vers YAML — collez le JSON ci-dessus et voyez instantanément une sortie sécurisée Norway. Utilisez notre convertisseur YAML vers JSON pour vérifier l’aller-retour.

Docker Compose depuis JSON

Les pipelines CI/CD génèrent parfois des configurations Docker Compose de manière programmatique depuis un store de configuration JSON, puis les écrivent sur disque en YAML pour que les développeurs les lisent.

Piège critique — politique de redémarrage :

{"restart_policy": "no"}

Dans Compose, restart_policy: "no" est une valeur valide signifiant « ne jamais redémarrer le conteneur ». Sans guillemets en YAML, cela devient restart_policy: false, que Docker Compose peut traiter comme la même sémantique (faux = pas de redémarrage) ou rejeter avec une erreur de validation de type — le comportement varie selon la version de Compose. Les guillemets sont obligatoires.

Surveiller aussi : La deploy.restart_policy.condition: "on-failure" de Compose v3 — la valeur on-failure contient le mot on, mais il est avec un tiret et n’est pas dans la liste des déclencheurs, donc c’est en fait sûr. Cependant, condition: on (sans le -failure) poserait problème. Mettez entre guillemets les valeurs de variables d’environnement dans le bloc environment: si elles pourraient être des mots Norway.

Validez les fichiers Compose après la conversion : docker-compose config analyse et ressort la forme canonique, révélant les erreurs de type.

Workflow GitHub Actions

Les workflows GitHub Actions sont des fichiers YAML édités à la main par les développeurs. Le scénario de conversion le plus courant est la lecture des données de workflow depuis l’API GitHub (qui retourne du JSON) et la conversion en fichier YAML local pour édition.

Les champs clés à surveiller :

# SÛR — pas de mots Norway dans les GitHub Actions standard
on:                        # "on" est une clé YAML ici, pas une valeur — géré différemment
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: |
          npm install
          npm test
        env:
          NODE_ENV: production   # sûr — pas un mot Norway
          DEBUG: "off"           # mot Norway en valeur — nécessite des guillemets

Note : on: comme clé YAML est spécial — le problème Norway s’applique aux valeurs, pas aux clés. Mais on comme valeur (comme DEBUG: on) déclencherait la coercition. Le bloc env: mérite une attention particulière car les valeurs de variables d’environnement sont des chaînes, mais beaucoup d’entre elles sont des drapeaux courts qui pourraient entrer en collision avec les mots Norway.

Pour les workflows incluant des spécifications shell:, les valeurs valides (bash, pwsh, sh, python) sont toutes sûres de la coercition Norway. Les valeurs personnalisées doivent être mises entre guillemets de manière préventive.

Plan Terraform JSON → YAML

terraform show -json tfplan > plan.json produit une représentation JSON détaillée de ce que Terraform planifie de créer, modifier ou détruire. Convertir cela en YAML le rend plus lisible pour les revues de pull request et les audits de conformité.

terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# Puis convertir avec notre outil ou une bibliothèque

Le JSON du plan Terraform est complexe et profond. Points d’attention clés lors de la conversion :

  1. Grands ID entiers. Les ID de ressources cloud (ID de comptes AWS, numéros de projets GCP) et les valeurs d’attributs calculées peuvent être de grands nombres. Convertissez via Python ou Go pour éviter la perte de précision float64.

  2. Chaînes de contrainte de version. Terraform utilise ~>, >=, <= dans les contraintes de version de fournisseur. Ces valeurs de chaîne sont gérées correctement par YAML tant qu’elles ne sont pas des mots Norway — mais ~> est sûr.

  3. Valeurs de configuration de fournisseur. Les sorties du plan Terraform peuvent inclure des valeurs de configuration pour les ressources. Si un champ booléen est par défaut false et représenté comme "no" dans un schéma de fournisseur, c’est un risque Norway au retour vers YAML.

  4. Le bloc .sensitive_values. Les valeurs sensibles sont expurgées comme booléens true dans le JSON du plan. Celles-ci survivent proprement à la conversion puisque true n’est pas un mot Norway dans aucune version YAML.

La conversion Terraform vers YAML est principalement pour la revue humaine, pas pour la réinjection dans Terraform. N’utilisez pas les manifestes YAML comme entrée Terraform — le format natif de Terraform est HCL, et son format d’entrée JSON est spécifique et documenté séparément.

Exemples de code — 4 langages

Node.js (eemeli/yaml + js-yaml)

L’écosystème Node.js dispose de deux bibliothèques YAML dominantes avec une gestion Norway significativement différente :

// eemeli/yaml — recommandé, YAML 1.2 par défaut, sécurisé Norway
import { stringify } from 'yaml';
import { readFileSync } from 'fs';

const jsonInput = readFileSync('input.json', 'utf8');
const data = JSON.parse(jsonInput);

// Par défaut : YAML 1.2 — "NO" reste "NO", pas de coercition booléenne
const yamlOutput = stringify(data);
console.log(yamlOutput);
// region: NO      ← sûr en 1.2, mais pour une compatibilité maximale mettez-le explicitement entre guillemets

// Forcer le comportement YAML 1.1 (pour les environnements K8s/Helm qui analysent 1.1)
const yamlForK8s = stringify(data, { version: '1.1' });
// region: 'NO'    ← mis automatiquement entre guillemets car 1.1 analyserait NO comme false
console.log(yamlForK8s);
// js-yaml — répandu, mais sémantique YAML 1.1, risqué Norway sans précaution
import yaml from 'js-yaml';
import { readFileSync } from 'fs';

const data = JSON.parse(readFileSync('input.json', 'utf8'));

// Dump par défaut — les mots Norway peuvent ne pas être entre guillemets
const unsafe = yaml.dump(data);
// region: NO    ← s'analysera comme false si relu par un analyseur 1.1 !

// Plus sûr : utiliser un schéma personnalisé ou forcer les guillemets
const safer = yaml.dump(data, {
  schema: yaml.JSON_SCHEMA,   // limite aux types compatibles JSON
  noCompatMode: false,
  lineWidth: -1,
  quotingType: '"',
  forceQuotes: false,         // met entre guillemets uniquement si nécessaire per le schéma JSON
});

Pour les nouveaux projets, préférez eemeli/yaml. Son défaut YAML 1.2 est plus sûr, son API Document donne un contrôle granulaire sur les guillemets, et elle gère mieux la fidélité aller-retour. Pour les projets utilisant déjà js-yaml, utilisez l’option JSON_SCHEMA pour se limiter aux types sûrs JSON. Pour un regard plus approfondi sur le filtrage et la transformation JSON avant la conversion, voir la fiche de référence jq en ligne de commande pour les modèles de pré-traitement.

Python (PyYAML + ruamel.yaml)

Python est le langage dominant pour les outils Kubernetes, Ansible et les pipelines d’ingénierie de données — tous de grands utilisateurs YAML.

import json
import yaml
import sys

# PyYAML — simple, standard, mais YAML 1.1 par défaut
with open('input.json') as f:
    data = json.load(f)

output = yaml.dump(data, default_flow_style=False, allow_unicode=True)
# country: 'NO'   ← PyYAML est assez intelligent pour auto-mettre les mots Norway entre guillemets
# Mais il ne met PAS "yes", "no" (minuscule) entre guillemets dans toutes les configurations :
# enabled: 'yes'   ← entre guillemets
# tag: y           ← peut ou non être entre guillemets selon la version

print(output)
import json
import sys
from ruamel.yaml import YAML

# ruamel.yaml — fidélité aller-retour, supporte YAML 1.2, recommandé pour la production
yaml_rt = YAML()
yaml_rt.default_flow_style = False
yaml_rt.width = 4096              # évite les retours à la ligne indésirables
yaml_rt.best_map_flow_style = False

with open('input.json') as f:
    data = json.load(f)

yaml_rt.dump(data, sys.stdout)
# Préserve l'ordre des clés, gère les mots Norway correctement, supporte les ancres en aller-retour

Pour les scripts d’automatisation Ansible et Kubernetes convertissant des réponses JSON en manifestes YAML, ruamel.yaml est le choix plus sûr. PyYAML convient pour les scripts simples où vous contrôlez les données d’entrée et avez vérifié qu’aucun mot Norway n’apparaît.

Si vous utilisez des fichiers de configuration JSON5 ou JSONC (avec commentaires) avant la conversion, supprimez d’abord les extensions — voir le guide de formatage JSON5 et JSONC pour les analyseurs compatibles.

Go (gopkg.in/yaml.v3)

Go est le langage de l’écosystème Kubernetes lui-même — kubectl, Helm, Argo, Flux et la plupart des opérateurs K8s sont écrits en Go.

package main

import (
    "encoding/json"
    "fmt"
    "os"

    "gopkg.in/yaml.v3"
)

func main() {
    // Lire l'entrée JSON
    jsonBytes, err := os.ReadFile("input.json")
    if err != nil {
        panic(err)
    }

    // Démarshaler JSON dans une map générique
    var data map[string]interface{}
    if err := json.Unmarshal(jsonBytes, &data); err != nil {
        panic(err)
    }

    // Marshaler vers YAML — yaml.v3 utilise la sémantique YAML 1.2
    yamlBytes, err := yaml.Marshal(data)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(yamlBytes))
    // country: "NO"     ← yaml.v3 met correctement les mots Norway entre guillemets
    // replicas: 3       ← les entiers restent des entiers
    // enabled: true     ← les booléens restent des booléens
}

yaml.v3 est une amélioration significative de yaml.v2 pour la sécurité Norway. La bibliothèque v2 suivait YAML 1.1 et écrirait NO sans guillemets ; v3 met correctement entre guillemets les valeurs ambiguës. Si vous maintenez un projet Go plus ancien utilisant v2, mettez à niveau vers v3 — l’API est largement compatible et l’amélioration de sécurité vaut la migration.

Pour la conversion type-safe avec des structs Go (plutôt que map[string]interface{}), utilisez les tags de struct :

type DeploymentLabels struct {
    App    string `yaml:"app" json:"app"`
    Region string `yaml:"region" json:"region"`
}
// yaml.Marshal sur un champ de struct contenant "NO" le mettra correctement entre guillemets en v3

CLI Bash (yq + jq)

Pour les scripts shell et les conversions ponctuelles rapides, yq (version Mike Farah, mikefarah/yq) convertit du JSON en YAML en une seule commande :

# Installer yq
brew install yq                         # macOS
sudo wget -qO /usr/local/bin/yq \
  https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
chmod +x /usr/local/bin/yq              # Linux

# Convertir un fichier JSON en YAML
yq -P < input.json > output.yaml

# Convertir depuis la sortie JSON kubectl
kubectl get deploy my-app -o json | yq -P > manifest.yaml

# Passer par jq d'abord pour filtrer/transformer, puis convertir en YAML
kubectl get deploy my-app -o json \
  | jq 'del(.status, .metadata.creationTimestamp, .metadata.managedFields)' \
  | yq -P > clean-manifest.yaml

Le pipeline jq | yq est un modèle puissant : utilisez jq pour la manipulation JSON (filtrage de champs, restructuration, interrogation de valeurs) et yq -P comme sérialiseur YAML final. Pour les modèles jq, voir la fiche de référence jq en ligne de commande pour 30 modèles du monde réel incluant des intégrations kubectl et aws.

Attention Norway avec yq : yq (mikefarah) respecte le type d’entrée depuis JSON — une chaîne JSON "NO" dans l’entrée se sérialisera comme une chaîne YAML avec guillemets. Mais si vous générez du YAML directement avec yq (pas depuis une entrée JSON), vous devez mettre explicitement entre guillemets les valeurs de mots Norway. Utilisez notre convertisseur YAML vers JSON pour valider l’aller-retour après la sortie yq.

Cas limites et pièges

Au-delà du problème Norway, la conversion JSON ↔ YAML a plusieurs cas limites qui piègent les ingénieurs expérimentés :

  1. YAML multi-document (séparateur ---). Un seul fichier YAML peut contenir plusieurs documents séparés par ---. JSON n’a pas de concept équivalent. Lors de la conversion de YAML multi-document vers JSON, la plupart des outils soit prennent uniquement le premier document, fusionnent tous les documents dans un tableau, soit échouent. Lors de la conversion de JSON vers YAML, un en-tête de document --- unique est ajouté par convention. Décidez et documentez explicitement votre comportement pour les pipelines pouvant rencontrer des fichiers multi-documents.

  2. Ancres et alias YAML. YAML supporte les définitions &anchor et les références *alias pour les configurations DRY. Lors de la conversion de YAML vers JSON, les ancres doivent être développées — le JSON résultant peut être beaucoup plus grand que le YAML source. Lors de la conversion de JSON vers YAML, le convertisseur ne peut pas reconstruire les ancres qui n’existaient pas dans l’original. Les alias sont une fonctionnalité YAML uniquement.

  3. Analyse implicite des horodatages. Les analyseurs YAML 1.1 convertissent 2024-05-04 et 2024-05-04T12:00:00Z en objets date natifs du langage, pas en chaînes. Lorsque cet objet date est sérialisé en JSON, la sortie dépend de la bibliothèque : certaines produisent des chaînes ISO, d’autres des horodatages Unix, d’autres null. Les dates en aller-retour via YAML sans guillemets de chaîne explicites ("2024-05-04") peuvent silencieusement changer le format.

  4. La balise !!binary. YAML peut intégrer des données binaires encodées en base64 avec la balise !!binary. JSON n’a pas de type binaire — le binaire doit être une chaîne base64. Lors de la conversion de YAML avec des champs !!binary vers JSON, décodez en chaîne base64. Au retour, vous ne pouvez pas reconstruire la balise binaire sans connaître le schéma. Kubernetes utilise !!binary pour certaines valeurs de secrets.

  5. Collisions de types de clés. JSON exige que les clés d’objet soient des chaînes. YAML autorise les clés de tout type — clés entières, clés booléennes, même des clés d’objets complexes. Un fichier YAML avec true: value ou 1: value comme clés ne peut pas être fidèlement représenté en JSON. La plupart des convertisseurs transforment les clés en chaînes, mais la sémantique change.

  6. Variance de représentation null. En YAML, null, ~, Null, NULL et une valeur vide signifient tous null. En JSON, seul null est null. Lors de la conversion de YAML vers JSON, tous ces éléments se normalisent en null. Mais lors de la conversion de JSON vers YAML, le choix de représentation null importe — ~ est plus compact, null est plus explicite. Choisissez-en un et restez cohérent.

  7. Changements d’ordre de tri. Les objets JSON n’ont techniquement pas d’ordre de clé défini (bien que la plupart des analyseurs préservent l’ordre d’insertion). Les mappings YAML n’ont de même pas d’ordre requis. Mais certaines bibliothèques YAML trient les clés alphabétiquement par défaut lors de la sérialisation. Cela peut causer de larges diffs dans le contrôle de version si le JSON source utilisait un ordre différent. Configurez sort_keys=False dans PyYAML (default_flow_style=False seul ne prévient pas le tri) et les options équivalentes dans d’autres bibliothèques.

Quand NE PAS convertir

La conversion n’est pas toujours la bonne réponse. Voici les scénarios où rester dans le format original est le meilleur choix :

Ne convertissez pas YAML en JSON si le YAML contient des commentaires documentant la logique métier. Les commentaires YAML ne font pas partie du modèle de données — ils disparaissent dans toute sérialisation vers JSON. Si un manifeste Kubernetes a des commentaires expliquant pourquoi une limite de ressources spécifique a été choisie ou pourquoi une exception de politique de sécurité a été faite, convertir en JSON détruit cette documentation. Gardez le YAML.

Ne convertissez pas automatiquement les configurations dans les pipelines CI sans tests aller-retour. Si votre pipeline convertit JSON en YAML puis applique le YAML à un cluster, ajoutez une étape de validation aller-retour : YAML vers JSON, puis comparez avec l’original. Cela détecte les surprises de coercition de type avant qu’elles n’atteignent la production.

Ne convertissez pas juste parce qu’un outil produit du JSON. kubectl, aws, terraform et docker inspect produisent tous du JSON, mais la plupart de ces outils acceptent aussi du YAML en entrée. Avant de construire une étape de conversion, vérifiez si l’outil cible peut directement accepter du YAML en entrée — la plupart des outils DevOps modernes le peuvent. Notre convertisseur YAML vers JSON est le plus utile quand vous avez spécifiquement besoin de JSON pour un outil qui n’accepte pas YAML.

Ne convertissez pas si les schémas diffèrent. Si votre JSON utilise des clés camelCase et que votre consommateur YAML attend snake_case (ou vice versa), vous avez besoin d’une étape de transformation en plus d’une conversion de format. Une conversion de format simple produira un YAML syntaxiquement correct mais sémantiquement erroné. Traitez le mapping de schéma explicitement.

Ne gardez pas les deux formats synchronisés manuellement. Si vous maintenez un config.json et un config.yaml qui sont supposés être équivalents, vous dériverez. Choisissez un format canonique et dérivez l’autre automatiquement — ou mieux, choisissez un format et éliminez la duplication.

FAQ

Le problème Norway de YAML affecte-t-il encore les systèmes modernes ?

Oui — c’est répandu dans l’écosystème. Kubernetes et Helm utilisent la bibliothèque yaml.v2 de Go (sémantique YAML 1.1) dans des parties significatives de leurs bases de code. Ansible utilise PyYAML (YAML 1.1). Les workflows GitHub Actions sont analysés par l’analyseur YAML interne de GitHub qui a son propre comportement. La plupart des fichiers YAML CI/CD dans la nature sont traités par des analyseurs YAML 1.1. Supposez la sémantique 1.1 jusqu’à ce que vous ayez vérifié autrement.

Pourquoi convertirais-je du JSON en YAML si YAML est plus difficile à analyser ?

La conversion ne porte pas sur la difficulté d’analyse — elle porte sur l’édibilité humaine. JSON est idéal pour les machines ; YAML est idéal pour les humains qui ont besoin de lire, éditer et réviser des fichiers de configuration. Un manifeste Kubernetes validé dans git, révisé dans des pull requests et ajusté à la main par des ingénieurs devrait être YAML. Le même manifeste récupéré depuis l’API pour un traitement programmatique devrait être JSON. Notre convertisseur JSON vers YAML fait le pont entre les deux.

Puis-je faire des allers-retours JSON ↔ YAML sans perte ?

Avec des mises en garde, oui — pour les données compatibles JSON. JSON est un sous-ensemble de YAML 1.2, donc tout document JSON valide est du YAML 1.2 valide. Aller JSON → YAML → JSON devrait être sans perte pour toutes les données sans coercition implicite de type. Le problème Norway signifie qu’une chaîne JSON "NO" pourrait survivre au passage aller seulement si le convertisseur la met entre guillemets, et survivre au retour seulement si l’analyseur YAML respecte les guillemets. Utilisez une bibliothèque YAML 1.2 dans les deux directions pour garantir des allers-retours sans perte.

Quelle est la bibliothèque YAML la plus sûre pour la production ?

Pour Python : ruamel.yaml configuré pour YAML 1.2. Pour Node.js : eemeli/yaml (le package yaml sur npm). Pour Go : gopkg.in/yaml.v3. Les trois implémentent la sémantique YAML 1.2 ou ont des modes YAML 1.2 explicites et gèrent correctement les mots Norway. Évitez les bibliothèques YAML 1.1 dans les nouveaux projets. Si vous devez utiliser une bibliothèque 1.1 (PyYAML, js-yaml, yaml.v2) pour des raisons de compatibilité, mettez toujours explicitement entre guillemets les chaînes susceptibles d’être problématiques Norway.

Les manifestes YAML Kubernetes supportent-ils les commentaires après une conversion JSON ?

Non — les commentaires ne peuvent pas être récupérés depuis JSON. JSON n’a pas de syntaxe de commentaire, donc il n’y a rien à convertir. Lorsque vous exécutez kubectl get deploy -o json et convertissez la sortie en YAML pour le stockage git, le YAML résultant n’aura pas de commentaires. Les commentaires dans un manifeste Kubernetes doivent être écrits par un humain après la conversion. C’est l’une des raisons pour lesquelles garder le YAML écrit à la main comme source canonique est souvent préférable à l’aller-retour via l’API JSON.

Comment gérer les grands entiers comme resourceVersion ou les horodatages en nanosecondes ?

metadata.resourceVersion de Kubernetes est un champ de chaîne délibérément — l’équipe Kubernetes savait que les analyseurs JSON en JavaScript et autres runtimes basés float64 perdraient en précision sur les grands entiers. Traitez-le toujours comme une chaîne. Pour les grands entiers genuinement numériques (comme les horodatages epoch en nanosecondes dans certains systèmes de traçage), utilisez le type int de Python, int64 de Go, ou BigInt de Node.js pour l’analyse. Ne les passez jamais par JSON.parse() en JavaScript sans une fonction de révision personnalisée. Lors de la conversion en YAML, ces grands entiers sont sûrs — YAML n’a pas de limite de précision pour les entiers. Le danger est dans l’aller-retour via l’analyseur JSON de JavaScript.

YAML 1.2 est-il largement adopté maintenant ?

De manière inégale. Les principales bibliothèques de langages ont migré : yaml.v3 de Go, ruamel.yaml de Python et eemeli/yaml de Node.js supportent ou sont par défaut sur YAML 1.2. Mais Kubernetes, Ansible et une grande partie de l’écosystème DevOps tourne encore sur des analyseurs YAML 1.1 en raison du coût de compatibilité ascendante de la migration. L’adoption de YAML 1.2 dans les nouveaux projets est recommandée, mais supposez la version 1.1 pour tout système que vous n’avez pas configuré vous-même.

Notre équipe devrait-elle standardiser sur JSON ou YAML pour les configurations ?

Standardisez sur l’objectif, pas sur le format. Utilisez JSON pour les configurations consommées par du code (corps de requêtes API, fichiers de configuration SDK, outillage programmatique). Utilisez YAML pour les configurations consommées par des humains (manifestes Kubernetes, pipelines CI, configs de déploiement, playbooks Ansible). Évitez de mélanger les deux pour la même configuration — choisissez une représentation par type de configuration et automatisez la conversion si vous avez besoin des deux. Quand vous devez convertir, nos convertisseurs JSON vers YAML et YAML vers JSON fonctionnent entièrement dans votre navigateur — aucune donnée ne quitte votre appareil.

Essayez maintenant

Prêt à convertir un vrai fichier ? Essayez notre convertisseur JSON vers YAML pour transformer du JSON en YAML Kubernetes sécurisé — il met automatiquement entre guillemets les mots Norway (NO, yes, on, off et la liste complète des booléens YAML 1.1) et vous permet de choisir une indentation de 2 ou 4 espaces. Pour la direction inverse, notre convertisseur YAML vers JSON gère les ancres, les alias et le YAML multi-document. Les deux outils fonctionnent entièrement dans votre navigateur — vos données ne quittent jamais votre appareil, ce qui importe quand vous travaillez avec des manifestes Kubernetes de production ou des plans Terraform contenant des configurations de ressources sensibles.

Articles connexes

Voir tous les articles