Skip to content
Terug naar blog
Tutorials

Het YAML Norway-probleem en JSON-YAML-verschillen voor engineers

Waarom YAML "no" als false leest. Echte K8s-storingen door aanhalingstekens. JSON vs. YAML-keuzes, inspringregels en K8s-manifestconversies uitgelegd.

14 min leestijd

Het YAML Norway-probleem en JSON ↔ YAML-verschillen die engineers moeten kennen

Het was een routinematige Helm-implementatie. Het team had twee dagen besteed aan het afstemmen van een values.yaml-bestand voor een implementatie in meerdere regio’s. De chart maakte een Kubernetes ConfigMap aan met locale-metadata — inclusief de landcode voor hun Noorse datacenter. Iemand typte country: NO en committede het. De CI-pipeline werd groen. De implementatie ging door.

Toen kwamen de waarschuwingen binnen.

De ConfigMap bevatte country: false in plaats van country: "NO". Elke downstream-service die het land-veld uitlas, kreeg een boolean in plaats van een string. De stringvergelijking brak. De routinglogica viel terug op een standaard. Verkeer dat in Noorwegen had moeten blijven, werd verwerkt door het verkeerde regionale eindpunt.

De oorzaak was één niet-aangehaalde string in een YAML-bestand. YAML 1.1 — de versie die vrijwel alle Kubernetes-tooling gebruikt — behandelt NO als een boolean false. Het behandelt YES, ON, OFF, Y, N, no, yes, on, off, y, n en een dozijn varianten op dezelfde manier. Geen waarschuwing. Geen fout. Stilzwijgend fout.

JSON heeft dit probleem niet. {"country": "NO"} is altijd een string. De impliciete typeconversie van YAML is zowel het grootste gemak als het gevaarlijkste struikelblok.

Deze gids behandelt het volledige beeld: waarom het Norway-probleem bestaat, wat er veranderde in YAML 1.2 (en waarom de meeste tooling het negeert), hoe je de juiste aanhalingstekenstrategie schrijft, de inspringregels die beginners laten struikelen, valkuilen met getalprecisie en vier praktische conversiescenario’s van Kubernetes-manifests tot Terraform-plannen. Als je JSON-waarden veilig naar YAML wilt omzetten zonder deze val, haalt onze JSON naar YAML omzetter automatisch aanhalingstekens rond Norway-gevoelige strings.

JSON vs. YAML — wanneer gebruik je wat?

Voordat we in het Norway-probleem duiken, helpt het te begrijpen waar elk formaat daadwerkelijk voor is geoptimaliseerd. Ze zijn niet uitwisselbaar — elk heeft een ontwerpcentrum dat het de betere keuze maakt in specifieke contexten.

DimensieJSONYAML
SyntaxisStrikt — accolades, aanhalingstekens, komma’s vereistFlexibel — op inspringing gebaseerd, minimale interpunctie
TypesysteemExpliciet: string, getal, boolean, null, array, objectImpliciet — YAML 1.1 leidt typen af uit de vorm van de waarde
Leesbaarheid voor mensenOntwikkelaarsvriendelijk, machinaal verifieerbaarMenselijk vriendelijk, gemakkelijk handmatig te bewerken
AanhalingstekenvereisteStrings altijd aangehaaldDe meeste scalars kunnen niet-aangehaald zijn (de bron van Norway)
CommentaarNiet ondersteundOndersteund met #
Primair gebruikAPI’s, gegevensuitwisseling, moderne configuratiesystemenKubernetes, Docker Compose, Ansible, CI-pipelines
Verrassende interpretatiesGeen — strikte verwerkingJa — Norway, octaal, tijdstempels
Schema-afdwingingJSON Schema-ecosysteemYAML Schema (minder tooling)

JSON wint wanneer je data systeemgrenzen overschrijdt — REST API’s, berichtenwachtrijen, databaseserialisatie. Machines verwerken het, machines genereren het, en de strikte syntaxis maakt validatie eenvoudig. Gebruik een JSON-formatter om de structuur te valideren voordat je verstuurt.

YAML wint wanneer mensen de primaire auteurs zijn. Kubernetes-manifests, GitHub Actions-workflows, Helm-charts, Ansible-playbooks — dit zijn bestanden die ontwikkelaars tientallen keren lezen en bewerken. De verminderde interpunctie en ondersteuning voor commentaar maken ze genuanceerd beter onderhoudbaar dan hun JSON-equivalenten.

Het probleem ontstaat aan de grens: wanneer een tool JSON genereert (zoals kubectl get deploy -o json of terraform show -json) en een mens het resultaat als YAML moet opslaan of bewerken. Daar leeft het Norway-probleem. Onze YAML naar JSON omzetter verwerkt de omgekeerde richting wanneer je terug moet.

Het Norway-probleem — diepgaand

Het Norway-probleem is geen bug. Het is een functie van de YAML 1.1-specificatie die precies werkt zoals ontworpen. Begrijpen waarom het zo is ontworpen — en waarom zoveel systemen nog steeds 1.1 implementeren — is de sleutel om het te vermijden.

Waarom “no”, “yes”, “on”, “off”, “y”, “n” verkeerd worden gelezen

De YAML 1.1-specificatie definieerde een breed boolean-type dat bedoeld was om menselijk vriendelijk te zijn. Het herkende alle volgende waarden als true of false:

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

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

De bedoeling was goed: configuratiebestanden gebruiken vaak yes/no in plaats van true/false in het Engels, en YAML wilde de natuurlijke manier ondersteunen waarop mensen configuratie schrijven. Het probleem is dat yes, no, on, off, y en n ook volkomen legitieme stringwaarden zijn die in de meeste applicaties iets heel anders betekenen.

Dit is de mismatch in concrete YAML:

# YAML 1.1 (wat de meeste parsers implementeren)
country: NO        # wordt verwerkt als: country: false   ← GEVAAR
enabled: yes       # wordt verwerkt als: enabled: true
restart: off       # wordt verwerkt als: restart: false
language: y        # wordt verwerkt als: language: true
shell: n           # wordt verwerkt als: shell: false

# Correct — expliciete aanhalingstekens overschrijven type-inferentie
country: "NO"      # wordt verwerkt als: country: "NO"    ← veilig
enabled: "yes"     # wordt verwerkt als: enabled: "yes"
restart: "off"     # wordt verwerkt als: restart: "off"
language: "y"      # wordt verwerkt als: language: "y"
shell: "n"         # wordt verwerkt als: shell: "n"

En de JSON-vergelijking:

{"country": "NO"}

In JSON is NO tussen aanhalingstekens altijd en onvoorwaardelijk een string. Er is geen impliciete type-inferentie. De striktheid die JSON verbose laat voelen, is ook wat het veilig maakt.

Naast boolean-omzetting converteert YAML 1.1 ook impliciet:

  • 123e4 → het getal 1230000 (wetenschappelijke notatie)
  • 0x1A → het getal 26 (hexadecimaal)
  • 0755 → het getal 493 (octaal — dit breekt Unix bestandspermissie-strings)
  • 2024-05-04 → een datumobject in veel parsers (niet alleen een string)
  • 1_000_000 → het getal 1000000 (onderstrepingstekenscheiding)

Het Norway-probleem is eigenlijk slechts het beroemdste lid van een hele familie YAML-impliciete typeconversies.

YAML 1.1 vs. 1.2 — wat veranderde

YAML 1.2 werd in 2009 gepubliceerd — vier jaar na YAML 1.1. Het primaire doel was YAML strikt in lijn te brengen met JSON (omdat JSON feitelijk een geldige YAML 1.2-subset is) en de verrassende impliciete typeconversies te verminderen.

In YAML 1.2:

  • Boolean is beperkt tot precies true en false (hoofdlettergevoelig). Dat is het. yes, no, on, off zijn gewone strings.
  • Octale literals vereisen het 0o-voorvoegsel (0o755) — de oude 0755-vorm is een string.
  • Tijdstempels worden niet impliciet verwerkt — 2024-05-04 blijft een string tenzij je het expliciet tagt.
  • De specificatie zelf is een JSON-superset, wat betekent dat elk geldig JSON-document geldig YAML 1.2 is.

Op papier lost YAML 1.2 het Norway-probleem volledig op. In de praktijk is het ecosysteem nauwelijks meegegaan.

BibliotheekStandaard specificatieNorway-risico
PyYAML (Python)YAML 1.1Ja — yaml.safe_load verwerkt NO nog als False
ruamel.yaml (Python)YAML 1.2 (optioneel)Instelbaar — standaard veiliger
js-yaml (Node.js)YAML 1.1Ja in oudere versies; nieuwere versies hebben FAILSAFE_SCHEMA-optie
eemeli/yaml (Node.js)YAML 1.2Nee — 1.2 standaard, of expliciet versiekiesbaar
gopkg.in/yaml.v2 (Go)YAML 1.1Ja
gopkg.in/yaml.v3 (Go)YAML 1.2Aanzienlijk veiliger
Kubernetes / HelmYAML 1.1 (via Go yaml.v2)Ja — historisch, zeer moeilijk te migreren
AnsibleYAML 1.1 (via PyYAML)Ja

De reden dat migratie traag verloopt, is achterwaartse compatibiliteit. Systemen die een decennium lang hebben vertrouwd op yes/no als booleans, kunnen dat gedrag niet stilzwijgend veranderen zonder bestaande configuraties te breken. Kubernetes in het bijzonder heeft een enorme geïnstalleerde basis waarbij het wijzigen van YAML-verwerkingssemantiek een cluster-brede grote verandering zou zijn.

De praktische conclusie: ga uit van YAML 1.1-semantiek in elk tool dat je niet expliciet anders hebt geconfigureerd. Zet altijd aanhalingstekens rond strings die verkeerd zouden kunnen worden gelezen als booleans, tijdstempels of getallen.

Hoe productiesystemen worden getroffen

De Noorse landcode is het meest aangehaalde voorbeeld omdat het contra-intuïtief is — NO ziet eruit als een voor de hand liggende afkorting, niet als een boolean. Maar het patroon herhaalt zich in veel praktische scenario’s:

IATA-luchthavencodes. De Noorse luchthaven Harstad/Narvik heeft code EVE. Veilig. Oslo Gardermoen is OSL. Ook veilig. Maar elke applicatie die YAML gebruikt om regionale luchthavencodes op te slaan, is één no-routecode verwijderd van een boolean false in productie.

Omgevingsvariabelewaarden. ON is een volkomen geldige omgevingsvariabelewaarde die “ingeschakeld” betekent in sommige oudere systemen. OFF is het tegenovergestelde. Configuraties migreren van shellscripts naar YAML zonder aanhalingstekens rond deze waarden introduceert stille typeconversie.

E-mailgebruikersvelden. Een gebruiker wiens voornaam of gebruikersnaam letterlijk n, y of een van de triggertekst is, wordt verkeerd geserialiseerd als de applicatie YAML produceert zonder aanhalingstekens. Dit is bijzonder verraderlijk omdat het alleen mislukt voor een subset van gebruikers.

Docker Compose-herstartbeleidswaarden. De waarde "no" van het restart_policy-veld betekent “niet herstarten.” Als het zijn aanhalingstekens verliest in een YAML-round-trip, wordt de waarde false, en Docker Compose kan het interpreteren als “geen herstartbeleid opgegeven” of een validatiefout geven — hoe dan ook is het herstart-gedrag van de container fout.

GitHub Actions shell:-veld. De geldige shellwaarden zijn bash, pwsh, python, sh, cmd, powershell. Geen van deze zijn Norway-woorden. Maar iemand die shell: yes of shell: on typt als placeholder tijdens het schrijven, kan verrast worden als YAML het omzet naar een boolean voordat de validator het zelfs maar ziet.

De oplossing is in alle gevallen hetzelfde: zet aanhalingstekens rond strings die semantisch strings zijn, ongeacht of een mens ze als trefwoorden zou herkennen. Onze JSON naar YAML omzetter past dit automatisch toe — elke waarde in de Norway-woordenlijst krijgt aanhalingstekens in de uitvoer.

Aanhalingstekenstrategie

Als je eenmaal begrijpt waarom Norway-woorden mismatch geven, is de oplossing het kiezen van de juiste aanhalingstekenstrategie voor je gebruik. YAML ondersteunt drie modi, elk met andere afwegingen.

Auto vs. Dubbel vs. Enkel

Automatische aanhalingstekens (aanbevolen voor de meeste conversies) laat de bibliotheek beslissen wanneer aanhalingstekens nodig zijn. Waarden die zonder aanhalingstekens verkeerd zouden worden gelezen — Norway-woorden, getallen, tijdstempels, strings die eruitzien als YAML-syntaxis — worden automatisch aangehaald. Al het andere blijft als een gewone scalar. Dit geeft de meest leesbare uitvoer terwijl het veilig blijft.

# Auto-modus uitvoer
name: Alice          # gewoon — geen dubbelzinnigheid
country: "NO"        # aangehaald — Norway-woord
age: 30              # gewoon — ondubbelzinnig getal
created: "2024-05-04" # aangehaald — zou anders als datum worden verwerkt
port: "8080"         # afhankelijk van bibliotheek — sommige halen numeriek uitziende strings aan

Dubbele aanhalingstekens zetten alle stringwaarden tussen dubbele aanhalingstekens. Dit is expliciet en auditeerbaar — elke lezer kan zien dat al deze waarden strings zijn zonder over de specificatie na te denken. De afweging is uitgebreidheid en verminderde menselijke leesbaarheid, met name voor diep geneste configuraties.

# Dubbele aanhalingstekenmodus
name: "Alice"
country: "NO"
replicas: "3"         # zelfs getallen worden strings — kan schemafouten veroorzaken

Wees voorzichtig: als je doelschema een getal verwacht en je serialiseert het als een aangehaalde string, zal de YAML-parser het correct als string typen, maar Kubernetes of een andere strikte verbruiker kan het veld afwijzen als het verkeerde type.

Enkele aanhalingstekens zijn een YAML-exclusieve functie — JSON heeft geen syntaxis met enkele aanhalingstekens. Enkele aanhalingstekens zijn letterlijk: er zijn geen escape-reeksen binnenin. Het enige speciale geval is dat een enkel aanhalingsteken in een string met enkele aanhalingstekens moet worden verdubbeld (''). Enkele aanhalingstekens zijn ideaal voor strings die backslashes of speciale tekens bevatten die in dubbele aanhalingstekens zouden moeten worden gescaped.

# Enkele aanhalingstekenmodus
pattern: 'C:\Users\alice\Documents'  # geen escape nodig
regex: '\d+\.\d+'                    # backslashes letterlijk

Voor JSON-naar-YAML-conversies die bedoeld zijn om terug naar JSON te gaan, geef de voorkeur aan Auto- of Dubbele modus. Strings met enkele aanhalingstekens introduceren een YAML-specifieke syntaxis die een YAML-bewuste parser op de terugweg vereist.

Blokscalars (| en >)

De blokscalarsyntaxis van YAML is echt handig voor meerregelige strings — iets wat JSON onhandig afhandelt met \n-escape-reeksen.

Letterlijke blokscalar | bewaart regelafbrekingen exact:

# Letterlijk blok — regelafbrekingen bewaard
script: |
  #!/bin/bash
  set -euo pipefail
  echo "Starting deployment"
  kubectl apply -f manifest.yaml

# Equivalent JSON-weergave (onleesbaar)
# {"script": "#!/bin/bash\nset -euo pipefail\necho \"Starting deployment\"\nkubectl apply -f manifest.yaml\n"}

Gevouwen blokscalar > verbindt regels met spaties, waardoor elke regelafbreking een spatie wordt (behalve lege regels, die regelafbrekingen worden):

# Gevouwen blok — regelafbrekingen worden spaties
description: >
  This service handles authentication
  for the entire platform. It supports
  OAuth2, SAML, and API key authentication.

# Resultaat: "This service handles authentication for the entire platform. It supports OAuth2, SAML, and API key authentication.\n"

Blokscalars zijn uitstekend voor het insluiten van TLS-certificaten, meerregelige shellscripts of SQL-queries in YAML-configuraties — scenario’s waarbij het JSON-equivalent een lange, gescapete, één-liner zou zijn die geen mens kan lezen.

Bij het omzetten van JSON naar YAML gebruiken de meeste omzetters (inclusief de onze) de Auto-modus en stellen meerregelige strings voor met blokscalars alleen wanneer ze ingebedde regelafbrekingen detecteren. Eenregelige strings krijgen flowscalars (aangehaald of gewoon). Gebruik onze JSON naar YAML omzetter om de uitvoer te zien voordat je het naar een manifest commit.

Inspringing — 2 vs. 4 spaties, tabs verboden

De inspringregels van YAML zijn strenger dan ze eruitzien. De specificatie heeft één absolute regel en één conventie die varieert per ecosysteem.

De absolute regel: tabs zijn verboden. Elk inspringniveau moet spaties gebruiken. Een tabblad-teken in een YAML-bestand is een verwerkingsfout in de meeste parsers:

# FOUT — tabs veroorzaken verwerkingsfouten
apiVersion: apps/v1
kind: Deployment
metadata:
	name: my-app     # ← tabblad-teken hier → ParseError

# CORRECT — alleen spaties
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app      # ← twee spaties

Het foutbericht dat je ziet, varieert per bibliotheek. In Python’s PyYAML:

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

In Go’s yaml.v3:

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

Configureer je editor om tabs uit te breiden naar spaties voor YAML-bestanden. Voeg in VS Code toe aan je werkruimteinstellingen: "[yaml]": { "editor.insertSpaces": true, "editor.tabSize": 2 }.

De conventie: 2 vs. 4 spaties. Beide zijn geldig. Ecosysteemconventies verschillen:

EcosysteemConventieReden
Kubernetes-manifests2 spatiesOfficiële documenten en voorbeelden gebruiken 2
Helm-charts2 spatiesVolgt K8s-conventie
Docker Compose2 spatiesOfficiële compose-specificatievoorbeelden
GitHub Actions2 spatiesOfficiële workflowvoorbeelden
Ansible-playbooks2 spatiesOfficiële documentatie
Traditionele configuraties4 spatiesPast bij standaard JSON-opmaak

Voor elk bestand dat door Kubernetes of Docker Compose wordt verwerkt, gebruik je 2 spaties. Voor zelfstandige configuratiebestanden die alleen door mensen en aangepaste tooling worden gelezen, werken beide — wees gewoon consistent binnen een bestand. Onze JSON naar YAML omzetter gebruikt standaard 2 spaties en laat je overschakelen naar 4 voor projecten die dat verkiezen.

Nog een regel: onderliggende elementen moeten verder inspringen dan hun bovenliggende, maar het aantal extra spaties kan elke positieve integer zijn (1, 2, 3, 4…) — zolang het consistent is binnen een blok. Gebruik in de praktijk altijd 2 of 4 voor leesbaarheid.

Getalverwerking bij JSON ↔ YAML

Beide formaten ondersteunen getallen, maar de randgevallen verschillen genoeg om productiebugs te veroorzaken.

Precisieverlies bij grote getallen

JavaScript’s Number-type is een 64-bit IEEE 754 float. Het kan gehele getallen exact weergeven tot 2^53 − 1 = 9.007.199.254.740.991. Daarboven gaat integerscaffe precisie verloren:

// JavaScript precisieverlies — dit is geen YAML-probleem, maar het beïnvloedt JSON-verwerking
JSON.parse('{"v": 9007199254740993}').v
// → 9007199254740992   (de 3 werd 2 — één bit verloren)

// Veilig — binnen het 2^53-bereik
JSON.parse('{"v": 9007199254740991}').v
// → 9007199254740991   (exact)

Dit is relevant voor JSON-naar-YAML-conversie in JavaScript-omgevingen omdat de precisie al verloren is voordat YAML-serialisatie begint. Kubernetes metadata.resourceVersion is een string-veld specifiek omdat resourceversies het veilige integerreik kunnen overschrijden. Andere velden die eruitzien als kleine getallen — observedGeneration, uid-componenten — zijn veiliger, maar elk int64-veld in een K8s-respons is potentieel beïnvloed.

Oplossingen:

  • Gebruik Python of Go voor conversiepipelines met grote getallen — beide verwerken willekeurige gehele getallen ingebouwd.
  • Gebruik in Node.js een JSON-parser die BigInt ondersteunt: JSON.parse(text, (_, v) => typeof v === 'number' && !Number.isSafeInteger(v) ? BigInt(v) : v).
  • Serialiseer velden die zonder verlies moeten worden omgezet als strings aan de bron.
  • Zoek bij het reviewen van omgezette YAML naar velden zoals resourceVersion, generation en tijdstempelafgeleide waarden.

Octaal- en hexadecimale eigenaardigheden

YAML 1.1 behandelt bepaalde op getallen lijkende strings als niet-decimale gehele getallen:

# YAML 1.1 verwerkingsverrassingen
permissions: 0755   # wordt verwerkt als octaal 493, niet decimaal 755
value: 0x1A         # wordt verwerkt als hex 26, niet string "0x1A"

# YAML 1.2-gedrag
permissions: 0755   # blijft integer 755 (decimaal) — octaal vereist 0o-voorvoegsel
permissions: 0o755  # wordt verwerkt als octaal 493 in zowel 1.1 als 1.2

# Veilig voor beide specificaties — aanhalingstekens rond elke waarde met voorloopnul
permissions: "0755"  # altijd de string "0755"

De octaalval is bijzonder gevaarlijk voor Unix-bestandspermissies, IP-adrescomponenten met voorloopnullen (sommige netwerkapparaten) en elke numerieke code die voorloopnullen gebruikt voor opvulling (postcodes, productcodes). Zet altijd aanhalingstekens rond deze waarden bij het handmatig schrijven van YAML, of zorg ervoor dat je omzetter ze aanhaalt — onze JSON naar YAML omzetter detecteert numerieke strings van JSON en bewaart hun stringtype.

Praktijkconversies

Het Norway-probleem en aanhalingstekensstrategieën worden concreet wanneer je ze toepast op echte conversiescenario’s.

Kubernetes-manifest vanuit JSON

De canonieke workflow: kubectl get deploy my-app -o json geeft je het live object als JSON. Je wilt het opschonen (verwijder status, creationTimestamp, beheerde velden) en het incheckken in git als een YAML-manifest.

Bron-JSON (ingekort):

{
  "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" }
          ]
        }]
      }
    }
  }
}

Verwachte YAML-uitvoer (met Norway-bescherming):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
    region: "NO"          # aangehaald — Norway-woord
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"           # aangehaald — Norway-woord
            - name: ENABLE_FEATURE
              value: "yes"          # aangehaald — Norway-woord

Merk op dat replicas: 3 niet aangehaald is — het is een legitiem geheel getal dat Kubernetes als getal verwacht. De Norway-woorden in labels en env-waarden zijn aangehaald. Een naïeve omzetter die YAML 1.1-booleans niet verwerkt, zou stilzwijgend region: false en value: false produceren.

Valideer na het omzetten met: kubectl apply --dry-run=client -f manifest.yaml. Dit vangt schemafouten op zonder de cluster aan te raken.

Probeer de conversie in onze JSON naar YAML omzetter — plak de JSON hierboven en zie direct Norway-veilige uitvoer. Gebruik onze YAML naar JSON omzetter om de round-trip te verifiëren.

Docker Compose vanuit JSON

CI/CD-pipelines genereren soms Docker Compose-configuraties programmatisch vanuit een JSON-configuratieopslag, en schrijven ze vervolgens als YAML naar schijf zodat ontwikkelaars ze kunnen lezen.

Kritieke val — herstartbeleid:

{"restart_policy": "no"}

In Compose is restart_policy: "no" een geldige waarde die “herstart de container nooit” betekent. Zonder aanhalingstekens in YAML wordt dit restart_policy: false, wat Docker Compose kan interpreteren als dezelfde semantiek (falsy = niet herstarten) of afwijzen met een typevalidatiefout — gedrag varieert per Compose-versie. De aanhalingstekens zijn verplicht.

Let ook op: Compose v3 deploy.restart_policy.condition: "on-failure" — de on-failure-waarde bevat het woord on, maar het is afgebroken en staat niet in de triggerlijst, dus het is eigenlijk veilig. Maar condition: on (zonder de -failure) zou mismatch geven. Zet aanhalingstekens rond omgevingsvariabelewaarden in het environment:-blok als ze Norway-woorden kunnen zijn.

Valideer Compose-bestanden na conversie: docker-compose config verwerkt en herproduceert de canonieke vorm, waarbij typefouten naar boven komen.

GitHub Actions-workflow

GitHub Actions-workflows zijn YAML-bestanden die handmatig door ontwikkelaars worden bewerkt. Het meest voorkomende conversiescenario is het lezen van workflowgegevens van de GitHub API (die JSON retourneert) en het omzetten naar een lokaal YAML-bestand voor bewerking.

De sleutelvelden om op te letten:

# VEILIG — geen Norway-woorden in standaard GitHub Actions
on:                        # "on" is hier een YAML-sleutel, niet een waarde — anders verwerkt
  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   # veilig — geen Norway-woord
          DEBUG: "off"           # Norway-woord in waarde — aanhalingstekens nodig

Opmerking: on: als YAML-sleutel is speciaal — het Norway-probleem geldt voor waarden, niet voor sleutels. Maar on als waarde (zoals DEBUG: on) zou de omzetting triggeren. Het env:-blok verdient bijzondere aandacht omdat omgevingsvariabelewaarden strings zijn, maar veel ervan zijn korte vlaggen die kunnen botsen met Norway-woorden.

Voor workflows die shell:-specificaties bevatten, zijn geldige waarden (bash, pwsh, sh, python) allemaal veilig voor Norway-omzetting. Aangepaste waarden moeten preventief worden aangehaald.

Terraform JSON-plan → YAML

terraform show -json tfplan > plan.json geeft een gedetailleerde JSON-weergave van wat Terraform van plan is te maken, wijzigen of vernietigen. Dit omzetten naar YAML maakt het beter leesbaar voor pull-requestreviews en compliance-audits.

terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# Vervolgens omzetten met onze tool of een bibliotheek

De Terraform-plan-JSON is complex en diep. Belangrijke aandachtspunten bij het omzetten:

  1. Grote integer-ID’s. Cloud-resource-ID’s (AWS-account-ID’s, GCP-projectnummers) en berekende attribuutwaarden kunnen grote getallen zijn. Zet via Python of Go om om float64-precisieverlies te vermijden.

  2. Versie-beperking strings. Terraform gebruikt ~>, >=, <= in providerversiesbeperkingen. Dit zijn stringwaarden die YAML correct verwerkt zolang ze geen Norway-woorden zijn — maar ~> is veilig.

  3. Providerconfiguratieschema-waarden. Terraform-planuitvoer kan configuratiewaarden voor resources bevatten. Als een boolean-veld standaard false is en als "no" wordt weergegeven in sommige providerschema’s, is dat een Norway-risico op de terugweg naar YAML.

  4. Het .sensitive_values-blok. Gevoelige waarden zijn verborgen als true-booleans in de plan-JSON. Deze overleven de conversie netjes omdat true geen Norway-woord is in een van beide YAML-versies.

De Terraform-naar-YAML-conversie is primair voor menselijke review, niet om terug in Terraform te voeren. Gebruik geen YAML-manifests als Terraform-invoer — het ingebouwde formaat van Terraform is HCL, en zijn JSON-invoerformaat is specifiek en afzonderlijk gedocumenteerd.

Codevoorbeelden — 4 talen

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

Het Node.js-ecosysteem heeft twee dominante YAML-bibliotheken met betekenisvol verschillende Norway-afhandeling:

// eemeli/yaml — aanbevolen, YAML 1.2 standaard, Norway-veilig
import { stringify } from 'yaml';
import { readFileSync } from 'fs';

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

// Standaard: YAML 1.2 — "NO" blijft als "NO", geen boolean-omzetting
const yamlOutput = stringify(data);
console.log(yamlOutput);
// region: NO      ← veilig in 1.2, maar voor maximale compatibiliteit expliciet aanhalingstekens

// Forceer YAML 1.1-gedrag (voor K8s/Helm-omgevingen die 1.1 verwerken)
const yamlForK8s = stringify(data, { version: '1.1' });
// region: 'NO'    ← automatisch aangehaald omdat 1.1 NO als false zou verwerken
console.log(yamlForK8s);
// js-yaml — wijdverspreid, maar YAML 1.1-semantiek, Norway-riskant zonder zorg
import yaml from 'js-yaml';
import { readFileSync } from 'fs';

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

// Standaard dump — Norway-woorden worden mogelijk niet aangehaald
const unsafe = yaml.dump(data);
// region: NO    ← wordt als false verwerkt als opnieuw gelezen door een 1.1-parser!

// Veiliger: gebruik een aangepast schema of forceer aanhalingstekens
const safer = yaml.dump(data, {
  schema: yaml.JSON_SCHEMA,   // beperkt tot JSON-compatibele typen
  noCompatMode: false,
  lineWidth: -1,
  quotingType: '"',
  forceQuotes: false,         // haalt alleen aan wanneer nodig per JSON-schema
});

Voor nieuwe projecten geef je de voorkeur aan eemeli/yaml. De standaard YAML 1.2 is veiliger, de Document API geeft fijnmazige controle over aanhalingstekens en het verwerkt de round-trip-getrouwheid beter. Voor projecten die al js-yaml gebruiken, gebruik je de optie JSON_SCHEMA om te beperken tot JSON-veilige typen.

Python (PyYAML + ruamel.yaml)

Python is de dominante taal voor Kubernetes-tooling, Ansible en data-engineeringpipelines — allemaal zware YAML-gebruikers.

import json
import yaml
import sys

# PyYAML — eenvoudig, standaard, maar YAML 1.1 standaard
with open('input.json') as f:
    data = json.load(f)

output = yaml.dump(data, default_flow_style=False, allow_unicode=True)
# country: 'NO'   ← PyYAML is slim genoeg om Norway-woorden automatisch aan te halen
# Maar het haalt "yes", "no" (kleine letters) niet in alle configuraties aan:
# enabled: 'yes'   ← aangehaald
# tag: y           ← al dan niet aangehaald afhankelijk van versie

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

# ruamel.yaml — round-trip-getrouwheid, ondersteunt YAML 1.2, aanbevolen voor productie
yaml_rt = YAML()
yaml_rt.default_flow_style = False
yaml_rt.width = 4096              # ongewenst regelombreken voorkomen
yaml_rt.best_map_flow_style = False

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

yaml_rt.dump(data, sys.stdout)
# Bewaart sleutelvolgorde, verwerkt Norway-woorden correct, ondersteunt ankers bij round-trip

Voor Ansible- en Kubernetes-automatiseringsscripts waarbij je JSON API-responses naar YAML-manifests omzet, is ruamel.yaml de veiligere keuze. PyYAML is prima voor eenvoudige scripts waarbij je de invoerdata beheert en hebt geverifieerd dat er geen Norway-woorden in voorkomen.

Go (gopkg.in/yaml.v3)

Go is de taal van het Kubernetes-ecosysteem zelf — kubectl, Helm, Argo, Flux en de meeste K8s-operators zijn geschreven in Go.

package main

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

    "gopkg.in/yaml.v3"
)

func main() {
    // Lees JSON-invoer
    jsonBytes, err := os.ReadFile("input.json")
    if err != nil {
        panic(err)
    }

    // Lees JSON als een generieke map
    var data map[string]interface{}
    if err := json.Unmarshal(jsonBytes, &data); err != nil {
        panic(err)
    }

    // Serialiseer naar YAML — yaml.v3 gebruikt YAML 1.2-semantiek
    yamlBytes, err := yaml.Marshal(data)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(yamlBytes))
    // country: "NO"     ← yaml.v3 haalt Norway-woorden correct aan
    // replicas: 3       ← gehele getallen blijven gehele getallen
    // enabled: true     ← booleans blijven booleans
}

yaml.v3 is een aanzienlijke verbetering ten opzichte van yaml.v2 voor Norway-veiligheid. De v2-bibliotheek volgde YAML 1.1 en zou NO zonder aanhalingstekens schrijven; v3 haalt ambigue waarden correct aan. Als je een ouder Go-project onderhoudt dat v2 gebruikt, upgrade dan naar v3 — de API is grotendeels compatibel en de veiligheidsverbetering is de migratie waard.

Voor type-veilige conversie met Go-structs (in plaats van map[string]interface{}), gebruik je struct-tags:

type DeploymentLabels struct {
    App    string `yaml:"app" json:"app"`
    Region string `yaml:"region" json:"region"`
}
// yaml.Marshal op een struct-veld dat "NO" bevat, haalt het correct aan in v3

Bash CLI (yq + jq)

Voor shellscripts en snelle eenmalige conversies converteert yq (de versie van Mike Farah, mikefarah/yq) JSON naar YAML in één opdracht:

# Installeer 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

# Zet JSON-bestand om naar YAML
yq -P < input.json > output.yaml

# Zet vanuit kubectl JSON-uitvoer om
kubectl get deploy my-app -o json | yq -P > manifest.yaml

# Pipe eerst via jq om te filteren/transformeren, dan naar YAML omzetten
kubectl get deploy my-app -o json \
  | jq 'del(.status, .metadata.creationTimestamp, .metadata.managedFields)' \
  | yq -P > clean-manifest.yaml

De jq | yq-pipeline is een krachtig patroon: gebruik jq voor JSON-manipulatie (velden filteren, structuur hervormen, waarden opvragen) en yq -P als de uiteindelijke YAML-serializer.

Norway-voorbehoud bij yq: yq (mikefarah) respecteert het invoertype van JSON — een JSON-string "NO" in de invoer wordt geserialiseerd als een YAML-string met aanhalingstekens. Maar als je YAML direct genereert met yq (niet vanuit JSON-invoer), moet je Norway-woordwaarden expliciet aanhalingstekens geven. Gebruik onze YAML naar JSON omzetter om de round-trip te valideren na yq-uitvoer.

Randgevallen en valkuilen

Naast het Norway-probleem heeft JSON ↔ YAML-conversie verschillende randgevallen die ervaren engineers laten struikelen:

  1. YAML met meerdere documenten (--- scheidingsteken). Een enkel YAML-bestand kan meerdere documenten bevatten gescheiden door ---. JSON heeft geen equivalent concept. Bij het omzetten van YAML met meerdere documenten naar JSON nemen de meeste tools alleen het eerste document, voegen alle documenten samen in een array of geven een fout. Bij het omzetten van JSON naar YAML wordt conventioneel één ----documentkop toegevoegd. Bepaal en documenteer je gedrag expliciet voor pipelines die bestanden met meerdere documenten kunnen tegenkomen.

  2. YAML-ankers en -aliassen. YAML ondersteunt &anker-definities en *alias-referenties voor DRY-configuraties. Bij het omzetten van YAML naar JSON moeten ankers worden uitgebreid — de resulterende JSON kan veel groter zijn dan de bron-YAML. Bij het omzetten van JSON naar YAML kan de omzetter geen ankers reconstrueren die niet in het origineel bestonden. Aliassen zijn een YAML-exclusieve functie.

  3. Impliciete tijdstempelverwerking. YAML 1.1-parsers converteren 2024-05-04 en 2024-05-04T12:00:00Z naar taalspecifieke datumobjecten, niet strings. Wanneer dit datumobject terug naar JSON wordt geserialiseerd, is de uitvoer afhankelijk van de bibliotheek: sommige produceren ISO-strings, sommige Unix-tijdstempels, sommige null. Datums door YAML heen laten gaan zonder expliciete aanhalingstekens ("2024-05-04") kan stilzwijgend het formaat veranderen.

  4. De !!binary-tag. YAML kan base64-geëncodeerde binaire data insluiten met de !!binary-tag. JSON heeft geen binair type — binaire data moet een base64-string zijn. Bij het omzetten van YAML met !!binary-velden naar JSON, decodeer naar base64-string. Bij het terugzetten kun je de binaire tag niet reconstrueren zonder het schema te kennen. Kubernetes gebruikt !!binary voor sommige secretwaarden.

  5. Sleuteltypeconflicten. JSON vereist dat objectsleutels strings zijn. YAML staat sleutels van elk type toe — integer-sleutels, boolean-sleutels, zelfs complexe objectsleutels. Een YAML-bestand met true: value of 1: value als sleutels kan niet getrouw als JSON worden weergegeven. De meeste omzetters zetten de sleutels om naar strings, maar de semantiek verandert.

  6. Variatie in null-weergave. In YAML betekenen null, ~, Null, NULL en een lege waarde allemaal null. In JSON is alleen null null. Bij het omzetten van YAML naar JSON worden al deze genormaliseerd naar null. Maar bij het terugzetten van JSON naar YAML is de keuze voor de null-weergave belangrijk — ~ is compacter, null is explicieter. Kies er één en houd je eraan.

  7. Volgordeveranderingen. JSON-objecten hebben technisch gezien geen gedefinieerde sleutelvolgorde (hoewel de meeste parsers invoegvolgorde bewaren). YAML-mappings hebben ook geen vereiste volgorde. Maar sommige YAML-bibliotheken sorteren sleutels standaard alfabetisch bij het serialiseren. Dit kan grote diffs in versiebeheer veroorzaken als de bron-JSON een andere volgorde gebruikte. Configureer sort_keys=False in PyYAML (default_flow_style=False alleen voorkomt het sorteren niet) en equivalente opties in andere bibliotheken.

Wanneer NIET om te zetten

Omzetting is niet altijd het juiste antwoord. Hier zijn de scenario’s waarbij in het oorspronkelijke formaat blijven de betere keuze is:

Zet YAML niet om naar JSON als de YAML commentaar bevat dat bedrijfslogica documenteert. YAML-commentaar maakt geen deel uit van het datamodel — het verdwijnt bij elke serialisatie naar JSON. Als een Kubernetes-manifest commentaar bevat dat uitlegt waarom een specifieke resourcelimiet is gekozen of waarom een beveiligingsbeleiduitzondering is gemaakt, vernietigt omzetten naar JSON die documentatie. Bewaar de YAML.

Zet configuraties in CI-pipelines niet automatisch om zonder round-trip-tests. Als je pipeline JSON naar YAML omzet en vervolgens de YAML op een cluster toepast, voeg dan een round-trip-validatiestap toe: YAML terug naar JSON, dan vergelijken met het origineel. Dit vangt typeomzettingsverrassingen op voordat ze productie bereiken.

Zet niet om omdat een tool JSON uitvoert. kubectl, aws, terraform en docker inspect produceren allemaal JSON, maar de meeste van deze tools accepteren ook YAML als invoer. Controleer voordat je een conversiestap bouwt of de doeltool direct YAML-invoer kan accepteren — de meeste moderne DevOps-tools kunnen dat. Onze YAML naar JSON omzetter is het meest nuttig wanneer je specifiek JSON nodig hebt voor een tool die YAML niet accepteert.

Zet niet om als de schema’s verschillen. Als je JSON camelCase-sleutels gebruikt en je YAML-verbruiker snake_case verwacht (of omgekeerd), heb je naast een formaatconversie ook een transformatiestap nodig. Een louter formaatconversie geeft syntactisch correcte maar semantisch onjuiste YAML. Pak de schemaomzetting expliciet aan.

Houd niet beide formaten handmatig synchroon. Als je een config.json en een config.yaml bijhoudt die equivalent zouden moeten zijn, zullen ze uiteindelijk uit elkaar lopen. Kies één canoniek formaat en leid het andere automatisch af — of kies één formaat en elimineer de duplicatie.

Veelgestelde vragen

Heeft het YAML Norway-probleem nog steeds invloed op moderne systemen?

Ja — het is wijdverspreid in het ecosysteem. Kubernetes en Helm gebruiken Go’s yaml.v2-bibliotheek (YAML 1.1-semantiek) in significante delen van hun codebases. Ansible gebruikt PyYAML (YAML 1.1). GitHub Actions-workflows worden verwerkt door de interne YAML-parser van GitHub met zijn eigen gedrag. De meeste CI/CD YAML-bestanden in het wild worden verwerkt door YAML 1.1-parsers. Ga uit van 1.1-semantiek totdat je anders hebt geverifieerd.

Waarom zou ik JSON naar YAML omzetten als YAML moeilijker te verwerken is?

De conversie gaat niet over moeilijkheid van verwerking — het gaat over menselijke bewerkbaarheid. JSON is ideaal voor machines; YAML is ideaal voor mensen die configuratiebestanden moeten lezen, bewerken en reviewen. Een Kubernetes-manifest dat in git is ingecheckt, in pull-requests wordt gereviewd en door engineers handmatig wordt afgestemd, moet YAML zijn. Hetzelfde manifest opgehaald van de API voor programmatische verwerking moet JSON zijn. Onze JSON naar YAML omzetter verbindt de twee.

Kan ik JSON ↔ YAML zonder verlies omzetten?

Met voorbehoud, ja — voor JSON-compatibele data. JSON is een subset van YAML 1.2, dus elk geldig JSON-document is geldige YAML 1.2. JSON → YAML → JSON zou verliesvrij moeten zijn voor data zonder impliciete typeomzetting. Het Norway-probleem betekent dat een JSON-string "NO" de heenreis alleen overleeft als de omzetter aanhalingstekens plaatst, en de terugkeer alleen overleeft als de YAML-parser de aanhalingstekens respecteert. Gebruik een YAML 1.2-bibliotheek voor beide richtingen om verliesvrije round-trips te garanderen.

Wat is de veiligste YAML-bibliotheek voor productie?

Voor Python: ruamel.yaml geconfigureerd voor YAML 1.2. Voor Node.js: eemeli/yaml (het yaml-pakket op npm). Voor Go: gopkg.in/yaml.v3. Alle drie implementeren YAML 1.2-semantiek of hebben expliciete YAML 1.2-modi en verwerken Norway-woorden correct. Vermijd YAML 1.1-bibliotheken in nieuwe projecten. Als je een 1.1-bibliotheek (PyYAML, js-yaml, yaml.v2) moet gebruiken voor compatibiliteitsredenen, zet altijd expliciet aanhalingstekens rond Norway-gevoelige strings.

Ondersteunt Kubernetes-manifest YAML commentaar na JSON-conversie?

Nee — commentaar kan niet worden hersteld vanuit JSON. JSON heeft geen commentaarsyntaxis, dus er is niets om om te zetten. Wanneer je kubectl get deploy -o json uitvoert en de uitvoer omzet naar YAML voor git-opslag, heeft de resulterende YAML geen commentaar. Commentaar in een Kubernetes-manifest moet door een mens worden geschreven na de conversie. Dit is één reden waarom het bewaren van de handgeschreven YAML als de canonieke bron vaak beter is dan het doorgaan via de JSON-API.

Hoe ga ik om met grote gehele getallen zoals resourceVersion of nanoseconde-tijdstempels?

Kubernetes metadata.resourceVersion is een string-veld bewust — het Kubernetes-team wist dat JSON-parsers in JavaScript en andere float64-gebaseerde runtimes precisie zouden verliezen bij grote gehele getallen. Behandel het altijd als een string. Voor echt numerieke grote gehele getallen (zoals nanoseconde-epoche-tijdstempels in sommige tracing-systemen), gebruik Python’s int-type, Go’s int64 of Node.js BigInt voor verwerking. Laat ze nooit door JSON.parse() in JavaScript gaan zonder een aangepaste revisor-functie. Bij het omzetten naar YAML zijn deze grote gehele getallen veilig — YAML heeft geen precisielimiet voor gehele getallen. Het gevaar zit in de round-trip terug via JavaScript’s JSON-parser.

Is YAML 1.2 al wijdverspreid?

Ongelijkmatig. De grote taalbibliotheken zijn aan het migreren: Go’s yaml.v3, Python’s ruamel.yaml en Node.js’s eemeli/yaml ondersteunen of gebruiken YAML 1.2 standaard. Maar Kubernetes, Ansible en veel van het DevOps-ecosysteem draait nog op YAML 1.1-parsers vanwege de achterwaartse-compatibiliteitskosten van migratie. YAML 1.2-adoptie in nieuwe projecten wordt aanbevolen, maar ga uit van 1.1 voor elk systeem dat je zelf niet hebt geconfigureerd.

Moet ons team standaardiseren op JSON of YAML voor configuraties?

Standaardiseer op doel, niet op formaat. Gebruik JSON voor configuraties die door code worden verwerkt (API-verzoeklichamen, SDK-configuratiebestanden, programmatische tooling). Gebruik YAML voor configuraties die door mensen worden verwerkt (Kubernetes-manifests, CI-pipelines, implementatieconfiguraties, Ansible-playbooks). Vermijd het mixen van de twee voor dezelfde configuratie — kies één weergave per configuratietype en automatiseer de conversie als je beide nodig hebt. Wanneer je wél moet omzetten, draaien zowel onze JSON naar YAML- als YAML naar JSON-omzetters volledig in je browser — je data verlaat je apparaat nooit.

Probeer het nu

Klaar om een echt bestand om te zetten? Probeer onze JSON naar YAML omzetter voor het veilig omzetten van JSON naar Kubernetes YAML — hij haalt automatisch aanhalingstekens rond Norway-woorden (NO, yes, on, off en de volledige YAML 1.1 boolean-lijst) en laat je 2 of 4 spaties inspringing kiezen. Voor de omgekeerde richting verwerkt onze YAML naar JSON omzetter ankers, aliassen en YAML met meerdere documenten. Beide tools draaien volledig in je browser — je data verlaat je apparaat nooit, wat belangrijk is als je werkt met productie-Kubernetes-manifests of Terraform-plannen met gevoelige resourceconfiguraties.

Gerelateerde artikelen

Alle artikelen bekijken