01: YAML e la frattura tra 1.1 e 1.2

Indice · successivo → 02 - Struttura - documenti, mapping, indentazione

1.1 Cos’è YAML e a cosa serve

YAML sta per YAML Ain’t Markup Language, acronimo ricorsivo, come GNU. Non è un linguaggio di markup: è un formato di serializzazione dati pensato per essere scritto e letto da esseri umani.

Tre cose lo distinguono da JSON: commenti, sintassi minimale (niente parentesi graffe, niente virgole) e frammenti riusabili (anchor). È per questo che ha vinto nel mondo delle configurazioni: un file di automazione Home Assistant o un workflow CI sono scritti e riletti da persone, non da programmi.

Il prezzo di quella leggibilità è la tipizzazione implicita: YAML indovina il tipo dei valori dall’aspetto. Ed è lì che nascono tutti i problemi.

1.2 Le versioni

VersioneDataStato
1.02004storia
1.12005quello che implementano molti parser reali
1.22009il cambiamento importante
1.2.21 ott 2021la specifica corrente, senza modifiche normative rispetto alla 1.2
1.3.0bozza 2022mai pubblicata, ferma

La 1.2 ha fatto una cosa sola, ma enorme: ha sostituito la libreria di tipi di YAML 1.1 con il “core schema”, molto più stretto. Elenco ufficiale dei cambiamenti:

  • Solo le stringhe true e false vengono lette come booleani (incluse True e TRUE); y, yes, on e i loro opposti diventano stringhe.
  • Gli underscore _ non si possono più usare dentro i numeri.
  • I valori ottali richiedono il prefisso 0o: 010 ora vale 10, non 8.
  • I formati binario e sessagesimale sono stati rimossi.
  • I tipi !!pairs, !!omap, !!set, !!timestamp e !!binary sono stati rimossi.
  • Le chiavi speciali merge << e value = sono state rimosse.

Tradotto: in YAML 1.2 NO è la stringa “NO”, 12:30 è la stringa “12:30”, 2026-08-21 è una stringa, e << non esiste.

1.3 Il problema: quasi nessuno ha aggiornato

Ecco lo stato reale dell’ecosistema ad agosto 2026:

LibreriaUltima versioneSemantica
PyYAML (Python)6.0.3YAML 1.1
ruamel.yaml (Python)0.19.xYAML 1.2 core
js-yaml (JS)5.3.0YAML 1.2 core
yaml (JS, eemeli)2.9.xYAML 1.2
go-yaml v3-ibrido dichiarato, progetto non manutenuto

Python è 1.1, JavaScript è 1.2, Go è a metà. E PyYAML è, di gran lunga, il parser YAML più diffuso al mondo: sta sotto Home Assistant, Ansible, e mille script.

1.4 La dimostrazione

Stesso file, due parser. ✅ verificato eseguendo PyYAML 6.0.3 e lo schema core 1.2:

ScriviYAML 1.1 (PyYAML)YAML 1.2 core
NOFalse'NO'
onTrue'on'
YesTrue'Yes'
0777511 (ottale)777 (decimale!)
0o777'0o777' (stringa)511
01234668 (ottale)1234
08'08' (stringa)8
12:30750 (sessagesimale)'12:30'
2026-08-21oggetto data'2026-08-21'
1e3'1e3' (stringa)1000.0
1.101.11.1
1_0001000'1_000'

Guarda bene la riga 0777: cambia valore, da 511 a 777, senza alcun errore. E 01234 in 1.1 è 668 mentre 01890 (che contiene un 8, cifra non ottale) resta stringa: lo stesso campo si comporta in modo diverso a seconda del dato.

Nota anche 1.10 → 1.1: quello succede in entrambi gli schemi. Passare a 1.2 non risolve tutto.

1.5 YAML è davvero un superset di JSON?

La specifica dice che l’obiettivo era proprio quello, e in pratica è quasi vero. Le eccezioni reali:

  1. Chiavi duplicate. JSON dice che “dovrebbero” essere uniche, YAML dice che devono. {"a":1,"a":2} è JSON legale e YAML illegale.
  2. I tab. Un file JSON indentato con tab: js-yaml lo accetta, PyYAML lo rifiuta con found character '\t' that cannot start any token. Qui è PyYAML a non essere conforme, ma il risultato pratico non cambia.

Corollario utile: JSON valido è (quasi sempre) YAML valido, quindi in un file YAML puoi sempre ripiegare sulla sintassi JSON quando vuoi essere inequivocabile. È esattamente l’idea dietro KYAML, il sottoinsieme che Kubernetes ha standardizzato nel 2026: flow style, tutte le stringhe fra doppi apici, niente ambiguità.

1.6 Cosa farne, in pratica

Non puoi scegliere il parser: lo sceglie l’applicazione che legge il tuo file. Quindi:

La regola che discende da tutto questo

Scrivi file che si comportano allo stesso modo in 1.1 e in 1.2. Si ottiene virgolettando ogni valore ambiguo. Non è pedanteria: è l’unico modo di avere un file che significa la stessa cosa ovunque.

# fragile: significa cose diverse a seconda di chi legge
paese: NO
versione: 1.10
porta: 0022
inizio: 12:30
attivo: yes
 
# robusto: identico in 1.1 e 1.2
paese: 'NO'
versione: '1.10'
porta: 22
inizio: '12:30'
attivo: true

Esercizi

  1. Crea un file con i valori della tabella §1.4 e leggilo con: python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('test.yaml')),indent=2,default=str))". Guarda coi tuoi occhi cosa diventa NO.
  2. Leggi lo stesso file con Node: node -e "console.log(require('js-yaml').load(require('fs').readFileSync('test.yaml','utf8')))". Confronta.
  3. Cerca nei tuoi file YAML esistenti (frontmatter compresi) tutti i valori che iniziano con zero o che sono sigle di due lettere maiuscole. Sono le tue bombe a orologeria.