04: Tipi, risoluzione implicita e trappole
← 03 - Scalari, quoting e blocchi multiriga · Indice · successivo → 05 - Anchor, alias, merge key e chiavi
4.1 Come YAML decide il tipo
Non c’è dichiarazione di tipo: YAML guarda l’aspetto del valore e lo confronta con una serie di espressioni regolari. Questa è la tabella normativa del core schema di YAML 1.2, verbatim dalla specifica:
| Espressione regolare | Diventa |
|---|---|
null | Null | NULL | ~ | null |
| (vuoto) | null |
true | True | TRUE | false | False | FALSE | booleano |
[-+]? [0-9]+ | intero decimale |
0o [0-7]+ | intero ottale |
0x [0-9a-fA-F]+ | intero esadecimale |
[-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )? | float |
[-+]? ( \.inf | \.Inf | \.INF ) | infinito |
\.nan | \.NaN | \.NAN | NaN |
| qualsiasi altra cosa | stringa |
Cose che si leggono da qui e che quasi nessuno sa:
- I booleani hanno solo tre grafie ciascuno: minuscolo, Capitalizzato, MAIUSCOLO.
tRueè una stringa. 0oe0xnon accettano il segno:-0o10è una stringa.- Il decimale accetta zeri iniziali:
007è l’intero 7 (lo zero si perde). - Un valore vuoto è null.
chiave:senza niente dopo significachiave: null. ""(stringa vuota quotata) non è null: è la stringa vuota.
In YAML 1.1 (PyYAML) la tabella è molto più larga: aggiunge yes/no/on/off ai booleani,
gli ottali senza prefisso (0777), i sessagesimali (12:30), le date e gli underscore nei
numeri.
4.2 La tabella delle trappole
✅ tutto verificato eseguendo PyYAML 6.0.3 e lo schema core 1.2.
| Scrivi | 1.1 (PyYAML) | 1.2 core | Cosa volevi |
|---|---|---|---|
NO | False | 'NO' | il codice della Norvegia |
no / off / yes / on | booleani | stringhe | quasi sempre una stringa |
1.10 | 1.1 | 1.1 | la versione 1.10 |
1.2.3 | '1.2.3' | '1.2.3' | ✓ per fortuna |
0777 | 511 | 777 | dei permessi |
01234 | 668 | 1234 | un CAP |
08 | '08' | 8 | un mese |
12:30 | 750 | '12:30' | un orario |
2026-08-21 | oggetto data | '2026-08-21' | dipende |
1e3 | '1e3' | 1000.0 | dipende |
0e1234 | '0e1234' | 0 | un hash di commit |
1_000 | 1000 | '1_000' | mille |
Le due righe da tatuarsi:
1.10 diventa 1.1 in entrambi gli schemi. Non è un problema di versione di YAML:
è un float, e i float non hanno gli zeri finali. Ogni numero di versione va virgolettato.
Gli zeri iniziali si perdono sempre, o peggio cambiano base. CAP, numeri di telefono, codici prodotto, ID: sono stringhe, non numeri, anche quando sembrano numeri.
4.3 Il “Norway problem”
Il nome viene dal caso classico: una lista di codici paese ISO.
paesi: [IT, FR, DE, NO]✅ verificato con PyYAML → ['IT', 'FR', 'DE', False].
Il codice della Norvegia è NO, che in YAML 1.1 è un booleano. Il dato non dà errore:
diventa semplicemente False e prosegue nel programma.
Una precisazione che circola sbagliata
Si legge spesso che questo comportamento sarebbe “conforme a YAML 1.2”. È falso. In 1.2
NOnon matcha nessuna regexp e diventa stringa. Il problema è YAML 1.1, e lo vedi perché PyYAML implementa la 1.1: non perché la specifica lo richieda.
Della stessa famiglia: ON (che pure è la sigla dell’Ontario), Y, N. Il criterio è
sempre lo stesso: abbreviazioni di due lettere.
E c’è un dettaglio ancora più sottile: la specifica 1.1 include anche y e n fra i
booleani, ma PyYAML li ha deliberatamente esclusi. ✅ verificato: n resta la stringa
'n'. Cioè nemmeno “YAML 1.1” è una risposta univoca.
4.4 Le date
In YAML 1.1 2026-08-21 diventa un oggetto data, non una stringa. In 1.2 è una stringa.
Conseguenze concrete:
- lo stesso file dà tipi diversi a seconda del parser;
json.dumps()esplode su un oggetto data (TypeError: not JSON serializable);- in Astro (che usa js-yaml 4) le date diventano oggetti Date, quindi in uno schema Zod
conviene sempre
z.coerce.date(): funziona sia con la stringa sia con l’oggetto.
Se ti serve una data come stringa, virgolettala. Se ti serve una data come data, sappi quale parser leggerà il file.
4.5 Forzare i tipi: i tag
Quando la risoluzione implicita non fa quello che vuoi, puoi essere esplicito:
a: !!str 123 # la stringa "123"
b: !!int '42' # l'intero 42
c: !!float 1 # 1.0Esistono anche i tag custom, che sono un’estensione dell’applicazione. Li incontri in
Home Assistant (!secret, !include) e in CloudFormation (!Ref).
I tag custom rompono i parser generici
✅ verificato:
a: !Ref Bucketcon PyYAML SafeLoader dàConstructorError: could not determine a constructor for the tag '!Ref'. Ogni volta che validi un file Home Assistant con uno strumento generico, ti serve--unsafe, oyaml.customTagsin VS Code. Vedi 06 - YAML nella pratica.
4.6 Null
Quattro modi di scriverlo, più il vuoto:
a: null
b: Null
c: NULL
d: ~
e: # ← anche questo è null
f: "" # ← questa è la stringa vuota, NON nullLa riga e è quella che ti frega: una chiave lasciata senza valore (perché stavi per
scriverlo e sei stato interrotto) è null valido, non un errore di sintassi.
4.7 La regola operativa che discende da tutto il modulo
Quando virgolettare
Virgoletta sempre:
- sigle e codici di due lettere (
'NO','ON')- versioni (
'1.10','2.0')- qualsiasi identificatore numerico: CAP, telefoni, IBAN, SKU, ID, hash (
'0e1234')- orari e durate (
'12:30')- date che devono restare stringhe
- colori esadecimali (
'#FF0000')- permessi ottali, oppure usa il decimale
- qualsiasi valore che inizia con un carattere speciale
Non virgolettare mai per abitudine i valori palesemente testuali: renderebbe il file illeggibile e nasconderebbe i casi che contano davvero.
Un aiuto strutturale: uno schema JSON nell’editor ti dice che versione deve essere una
stringa mentre stai scrivendo. È più efficace di qualsiasi disciplina personale
(07 - Strumenti, sicurezza, debug e reference).
Esercizi
- Metti in un file tutti i valori della tabella §4.2 e leggili con PyYAML. Poi con Node. Tieni il file: è il tuo banco di prova quando incontri un dubbio.
- Scrivi una lista di dieci codici paese che includa
NO,ONeIT. Falla funzionare. - Prendi un tuo file YAML reale e cerca versioni, porte, codici e orari non virgolettati.
- Prova
!!str 123e verifica che il tipo cambi davvero.