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.
| Dimensie | JSON | YAML |
|---|---|---|
| Syntaxis | Strikt — accolades, aanhalingstekens, komma’s vereist | Flexibel — op inspringing gebaseerd, minimale interpunctie |
| Typesysteem | Expliciet: string, getal, boolean, null, array, object | Impliciet — YAML 1.1 leidt typen af uit de vorm van de waarde |
| Leesbaarheid voor mensen | Ontwikkelaarsvriendelijk, machinaal verifieerbaar | Menselijk vriendelijk, gemakkelijk handmatig te bewerken |
| Aanhalingstekenvereiste | Strings altijd aangehaald | De meeste scalars kunnen niet-aangehaald zijn (de bron van Norway) |
| Commentaar | Niet ondersteund | Ondersteund met # |
| Primair gebruik | API’s, gegevensuitwisseling, moderne configuratiesystemen | Kubernetes, Docker Compose, Ansible, CI-pipelines |
| Verrassende interpretaties | Geen — strikte verwerking | Ja — Norway, octaal, tijdstempels |
| Schema-afdwinging | JSON Schema-ecosysteem | YAML 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 getal1230000(wetenschappelijke notatie)0x1A→ het getal26(hexadecimaal)0755→ het getal493(octaal — dit breekt Unix bestandspermissie-strings)2024-05-04→ een datumobject in veel parsers (niet alleen een string)1_000_000→ het getal1000000(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
trueenfalse(hoofdlettergevoelig). Dat is het.yes,no,on,offzijn gewone strings. - Octale literals vereisen het
0o-voorvoegsel (0o755) — de oude0755-vorm is een string. - Tijdstempels worden niet impliciet verwerkt —
2024-05-04blijft 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.
| Bibliotheek | Standaard specificatie | Norway-risico |
|---|---|---|
| PyYAML (Python) | YAML 1.1 | Ja — yaml.safe_load verwerkt NO nog als False |
| ruamel.yaml (Python) | YAML 1.2 (optioneel) | Instelbaar — standaard veiliger |
| js-yaml (Node.js) | YAML 1.1 | Ja in oudere versies; nieuwere versies hebben FAILSAFE_SCHEMA-optie |
| eemeli/yaml (Node.js) | YAML 1.2 | Nee — 1.2 standaard, of expliciet versiekiesbaar |
| gopkg.in/yaml.v2 (Go) | YAML 1.1 | Ja |
| gopkg.in/yaml.v3 (Go) | YAML 1.2 | Aanzienlijk veiliger |
| Kubernetes / Helm | YAML 1.1 (via Go yaml.v2) | Ja — historisch, zeer moeilijk te migreren |
| Ansible | YAML 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:
| Ecosysteem | Conventie | Reden |
|---|---|---|
| Kubernetes-manifests | 2 spaties | Officiële documenten en voorbeelden gebruiken 2 |
| Helm-charts | 2 spaties | Volgt K8s-conventie |
| Docker Compose | 2 spaties | Officiële compose-specificatievoorbeelden |
| GitHub Actions | 2 spaties | Officiële workflowvoorbeelden |
| Ansible-playbooks | 2 spaties | Officiële documentatie |
| Traditionele configuraties | 4 spaties | Past 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,generationen 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:
-
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.
-
Versie-beperking strings. Terraform gebruikt
~>,>=,<=in providerversiesbeperkingen. Dit zijn stringwaarden die YAML correct verwerkt zolang ze geen Norway-woorden zijn — maar~>is veilig. -
Providerconfiguratieschema-waarden. Terraform-planuitvoer kan configuratiewaarden voor resources bevatten. Als een boolean-veld standaard
falseis en als"no"wordt weergegeven in sommige providerschema’s, is dat een Norway-risico op de terugweg naar YAML. -
Het
.sensitive_values-blok. Gevoelige waarden zijn verborgen alstrue-booleans in de plan-JSON. Deze overleven de conversie netjes omdattruegeen 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:
-
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. -
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. -
Impliciete tijdstempelverwerking. YAML 1.1-parsers converteren
2024-05-04en2024-05-04T12:00:00Znaar 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. -
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!!binaryvoor sommige secretwaarden. -
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: valueof1: valueals sleutels kan niet getrouw als JSON worden weergegeven. De meeste omzetters zetten de sleutels om naar strings, maar de semantiek verandert. -
Variatie in null-weergave. In YAML betekenen
null,~,Null,NULLen een lege waarde allemaal null. In JSON is alleennullnull. Bij het omzetten van YAML naar JSON worden al deze genormaliseerd naarnull. Maar bij het terugzetten van JSON naar YAML is de keuze voor de null-weergave belangrijk —~is compacter,nullis explicieter. Kies er één en houd je eraan. -
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=Falsein PyYAML (default_flow_style=Falsealleen 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.