Convertitore da JSON a YAML
Converte JSON in YAML e spiega ogni virgoletta che aggiunge: le stringhe che senza di essa diventerebbero booleani, numeri o date in silenzio.
name: deploy
country: 'NO'
startsAt: '12:30'
mode: '0755'
version: '1.10'
released: '2024-01-30'
enabled: 'yes'
script: |-
set -e
npm run build
npm test
replicas: 3
tags:
- web
- edge
Valori fra virgolette: 6. Richieste solo da YAML 1.1: 4. Cambia lo schema qui sopra per vedere la differenza.
countrysolo 1.1«NO» verrebbe letto come il booleano false.
startsAtsolo 1.1«12:30» verrebbe letto in base 60 come 750.
mode«0755» ha uno zero iniziale, quindi verrebbe letto come il numero 493.
version«1.10» verrebbe letto come il numero 1.1.
releasedsolo 1.1«2024-01-30» verrebbe letto come una data e non come testo.
enabledsolo 1.1«yes» verrebbe letto come il booleano true.
Che cosa fa questo strumento
Converte un documento JSON in YAML e poi ti dice perché ciascuna stringa è finita fra virgolette. Quella seconda parte è la ragione per cui lo strumento esiste: ogni altro convertitore restituisce l’output e ti lascia scoprire più tardi che uno dei tuoi valori non è più una stringa.
La conversione va in un solo verso. Leggere YAML è un problema assai più grande che scriverlo, e un analizzatore YAML parzialmente corretto è peggio di nessuno: accetta il tuo file e restituisce dati sbagliati senza lamentarsi. Emettere è un problema delimitato, ed è il verso coperto qui.
Perché un convertitore ha bisogno di opinioni
JSON dice di che tipo è ogni cosa. Una stringa ha le virgolette, un numero no, e non esiste una terza possibilità. YAML invece decide il tipo di un valore non quotato guardandone la forma: se corrisponde al modello di un booleano è un booleano, se corrisponde a un numero è un numero, e solo se non corrisponde a nulla resta testo.
È questo che rende YAML piacevole da scrivere a mano e che fa della conversione una questione di giudizio. Ogni stringa dell’input va confrontata con ogni modello che YAML risolve, e messa fra virgolette se ne incontra uno. Sbaglia dal lato prudente e l’output è rumoroso; sbaglia dall’altro e un valore cambia tipo in silenzio.
Il problema della Norvegia e i suoi parenti
Il caso più noto è un elenco di codici paese. La Norvegia è NO, e in YAML 1.1 il token non quotato NO è il booleano false. Un file di configurazione che elenca paesi perde la Norvegia e guadagna un false, e da nessuna parte nulla segnala un errore.
Non è una regola strana isolata ma un’intera famiglia. YAML 1.1 legge y, Y, yes, no, on e off come booleani, in qualsiasi grafia, e così cattura un simbolo chimico, la posizione di un interruttore e la risposta a una domanda. E i risolutori numerici sono ancora più strani:
- 12:30 è 750. YAML 1.1 legge cifre separate da due punti in base 60, quindi un’ora del giorno o una durata diventa un intero.
- 0755 è 493. Uno zero iniziale significa ottale in YAML 1.1 — e in YAML 1.2 lo stesso testo è il decimale 755: le due versioni discordano su quale numero, non sul fatto che lo sia.
- 1.10 è 1.1. Un numero di versione in due parti è un decimale, e lo zero finale sparisce. Una dipendenza fissata a 1.10 ora punta a 1.1.
- 2024-01-30 è un oggetto data e non una stringa, perché YAML 1.1 ha un tipo marca temporale.
- Una stringa vuota è null, come lo sono le parole nude null, Null, NULL e la tilde.
Nessuno di questi è un difetto di YAML. Sono i risolutori che fanno esattamente ciò che promettono, su un testo che per caso corrisponde. L’unica difesa è mettere fra virgolette tutto ciò che corrisponde, che è quel che fa questo strumento e quel che il pannello dei riscontri rende conto riga per riga.
Due versioni, e perché quella vecchia è predefinita
YAML 1.2 è arrivato nel 2009 e ha rimosso quasi tutti i risolutori sorprendenti. Il suo schema base tiene solo true e false come booleani, abbandona del tutto la base 60 e non ha un tipo marca temporale. Sotto 1.2, NO e 12:30 e 2024-01-30 sono semplicemente stringhe.
L’insidia è che cosa legga davvero il tuo file. PyYAML implementa YAML 1.1, e PyYAML sta dietro a una quantità enorme di strumenti: Ansible, vecchi client Kubernetes, innumerevoli script. yaml.v3 di Go e l’attuale js-yaml seguono 1.2. Lo stesso documento può quindi essere letto in due modi diversi a seconda di chi lo apre, e l’unico output sicuro ovunque è quello quotato per 1.1.
È questa la predefinita qui. Passare a 1.2 non nasconde nulla: riemette con i risolutori più recenti e il pannello dei riscontri si accorcia, così vedi con precisione quali virgolette c’erano per lo schema vecchio. Quelle che restano sono quelle di cui ogni analizzatore ha bisogno.
Stringhe che rompono la sintassi, non il tipo
Un secondo gruppo di stringhe va quotato per un motivo diverso: non perché YAML le leggerebbe come un altro tipo, ma perché non si analizzerebbero affatto come testo.
- Due punti seguiti da uno spazio chiudono una chiave. «note: time: now» verrebbe letto come una chiave note il cui valore è una chiave time.
- Uno spazio seguito da un cancelletto apre un commento, quindi tutto ciò che segue sparisce.
- Un -, ?, :, [, ], {, }, #, &, *, !, |, >, %, @ o accento grave iniziale è un carattere indicatore e ha un significato strutturale.
- Uno spazio iniziale o finale non viene conservato da un valore non quotato, quindi « x » torna come «x».
- Una tabulazione ovunque nel valore viene respinta del tutto: PyYAML rifiuta l’intero documento invece di leggerlo male, quindi questo caso fallisce rumorosamente.
Gli apici singoli si usano ovunque bastino, perché hanno esattamente una regola di escape — un apostrofo si scrive due volte — e si leggono meglio degli escape con barra rovesciata che portano le virgolette doppie. Queste ultime restano riservate a ciò che ha davvero bisogno di escape: caratteri di controllo, tabulazioni e stringhe su più righe che non possono usare un blocco.
Stringhe su più righe e l’indicatore di taglio
Una stringa che contiene ritorni a capo — uno script, un certificato, un blocco di prosa — è di solito il motivo per cui si vuole YAML in primo luogo. JSON può scriverla solo con escape barra-n su un’unica riga lunghissima; YAML ha lo scalare a blocco letterale, introdotto da una barra verticale, dove il testo compare rientrato e leggibile sotto.
La sottigliezza sta in che cosa accade ai ritorni a capo finali, e lo governa l’indicatore di taglio:
- Una barra verticale nuda taglia: per quanti ritorni finali abbia il blocco, il valore ne tiene esattamente uno.
- Una barra verticale seguita da un meno elimina: il valore non ne tiene nessuno.
- Una barra verticale seguita da un più conserva: il valore li tiene tutti.
Questo strumento sceglie l’indicatore dalla stringa che ha ricevuto, così il valore sopravvive esattamente al viaggio di andata e ritorno. Vale la pena saperlo perché la predefinita — la barra nuda — è quella che si scrive a mano, e normalizza in silenzio una stringa che finiva con due ritorni a capo o con nessuno.
Uno scalare a blocco non può portare tutto, e dove non può, l’output ripiega sulle virgolette doppie e il pannello dei riscontri dice perché. Un ritorno a capo di tipo CR non sopravvive, perché gli scalari a blocco normalizzano le interruzioni di riga. Una prima riga che inizia con uno spazio verrebbe letta come rientro aggiuntivo e tolta. E una riga che finisce con uno spazio è conservata dalla specifica, ma è invisibile a schermo e la maggior parte degli editor la elimina al salvataggio: quotarla è quindi più sicuro — è una decisione e non un limite, e viene segnalata come tale.
Più di un documento
YAML ha qualcosa che JSON non ha: un file può contenere un flusso di documenti separati da tre trattini. È il formato di un manifesto Kubernetes, ed è il motivo per cui un array JSON tanto spesso deve diventare qualcosa di diverso da una sequenza YAML.
L’interruttore qui emette ogni elemento di un array di primo livello come documento a sé. E quando l’input non è affatto un unico valore JSON ma ogni riga si analizza da sola, viene letto come NDJSON — il formato delimitato da righe in cui arrivano log ed esportazioni di API — e ogni riga diventa un documento. Quella lettura è una supposizione, quindi viene segnalata sopra l’output invece che fatta in silenzio.
Il ripiego si applica solo quando l’intero input fallisce l’analisi e ogni riga riesce, cosa che un documento semplicemente malformato non farà. Un errore di sintassi resta un errore di sintassi, con la riga e la colonna in cui si è verificato.
Ciò che la conversione non può conservare
Due cose si perdono prima che questo strumento veda i tuoi dati, entrambe nell’analisi JSON stessa, e conviene sapere quali.
Chiavi duplicate. JSON permette a un oggetto di elencare la stessa chiave due volte e la maggior parte degli analizzatori tiene l’ultima in silenzio. YAML vieta i duplicati del tutto, quindi l’output sarà valido, ma il valore precedente è già andato — e nessun convertitore può segnalare ciò che non ha mai ricevuto.
Precisione degli interi. Un numero JSON maggiore di circa novemila miliardi di milioni non sopravvive all’analisi in un double, quindi un identificatore come 12345678901234567890 torna arrotondato. Non è un problema di YAML né uno introdotto da questo strumento; accade in ogni analizzatore JSON del linguaggio. Se un identificatore grande conta, va messo in una stringa da entrambe le parti.
Note sull’output
Il rientro è a spazi, sempre, perché YAML vieta del tutto le tabulazioni per rientrare: è una delle poche cose su cui il formato è severo. Due spazi sono la convenzione; quattro sono offerti perché alcuni stili aziendali li vogliono.
Le sequenze sono rientrate sotto la loro chiave. Sia questa forma sia quella non rientrata sono YAML valido e significano la stessa cosa; la rientrata è quella che scrive la maggior parte delle persone e che la maggior parte degli editor ripiega correttamente.
Un array o un oggetto vuoto si scrive in stile a flusso come una coppia di parentesi, perché lo stile a blocco non ha modo di esprimere il vuoto: non c’è nulla da scrivere sulle righe seguenti.
L’output termina con un ritorno a capo, e questo è funzionale e non estetico. Il taglio di uno scalare a blocco si misura sull’interruzione di riga che lo segue, quindi un blocco tagliato proprio in fondo a un file senza ritorno finale perde il ritorno che avrebbe dovuto conservare.
Domande frequenti
- JSON è già YAML valido?
- Sotto YAML 1.2 sì: la specifica lo dice esplicitamente e un analizzatore 1.2 legge un file JSON direttamente. In pratica serve a poco, perché il motivo per convertire è la leggibilità — commenti, scalari a blocco, niente graffe — e incollare JSON in un file YAML non te ne dà nessuna. Sotto YAML 1.1 non è del tutto vero, il che è un motivo in più per distinguere le due versioni.
- Perché la mia stringa ha ricevuto virgolette di cui non sembra avere bisogno?
- Quasi certamente ne ha bisogno. YAML tipizza un valore non quotato confrontando modelli, quindi NO, yes, off, 12:30, 0755, 1.10, 2024-01-30 e la stringa vuota smettono tutti di essere stringhe. Il pannello dei riscontri nomina ciascuno e mostra il valore in cui si sarebbe trasformato, così l’affermazione si verifica invece di essere creduta. Se punti a un analizzatore YAML 1.2, cambiare schema toglie quelle che servono solo a 1.1.
- Qual è qui la differenza fra YAML 1.1 e 1.2?
- 1.2 ha abbandonato i risolutori che causano quasi tutte le sorprese: yes/no/on/off non sono più booleani, la base 60 è sparita e non esiste un tipo marca temporale. PyYAML implementa 1.1 ed è ancora ovunque, quindi l’output prudente è quello predefinito; l’impostazione 1.2 c’è per quando sai che cosa leggerà il file.
- Può riconvertire YAML in JSON?
- No, di proposito. Un lettore YAML ha bisogno di àncore, alias, tag, chiavi di fusione, cinque stili di scalare e due versioni di schema, e sbagliare finemente su uno qualsiasi significa accettare un file e restituire dati diversi da quelli che conteneva. Quel fallimento è silenzioso, il che lo rende peggiore che non offrire affatto la funzione.
- Come ottengo un file multidocumento in stile Kubernetes?
- Attiva l’interruttore che emette ogni elemento di un array di primo livello come documento a sé, e l’array diventa documenti separati da tre trattini. Se il tuo input è NDJSON — un oggetto JSON per riga, come spesso arrivano log ed esportazioni di API — viene rilevato automaticamente e segnalato sopra l’output.
- Perché non ci sono commenti nell’output?
- Perché non ce n’erano nell’input. I commenti sono la cosa principale che YAML ha e JSON no, e un convertitore non può inventarli. Vale la pena ricordarlo anche nell’altro verso: se fai passare un file YAML per JSON e ritorno, ogni suo commento è sparito.
- Qualcosa di ciò che incollo viene inviato a un server?
- No. L’analisi e la conversione avvengono interamente nel tuo browser; nulla viene caricato o registrato, e funziona senza connessione di rete.