Converter YAML em JSON
O YAML para JSON converte um documento YAML para JSON no seu navegador usando o esquema core do YAML 1.2. Isso importa mais do que parece: sob o antecessor do 1.2 ainda usado por PyYAML e Ruby, os tokens sem aspas NO, yes, on e off se resolvem como booleanos, então uma lista de códigos ISO de países perde a Noruega. Aqui eles continuam strings, e qualquer coisa que se resolveria de forma diferente sob o 1.1 é sinalizada.
Como funciona o Converter YAML em JSON?
YAML parece simples e não é. A especificação é mais longa do que as de JSON, XML e TOML somadas, e a maior parte das surpresas vem de uma decisão de design: escalares sem aspas são resolvidos por padrão de texto, e não declarados por sintaxe. O que um token significa depende de qual tabela de resolução o leitor está usando.
O problema da Noruega é um problema de versionamento
O YAML 1.1 resolvia y, yes, on, n, no e off como booleanos. Então countries: [NO, SE, DK] carregava como [false, "SE", "DK"], e um arquivo de configuração que dizia norway: no significava algo que ninguém pretendia. O YAML 1.2 removeu todos eles, junto com os números sexagesimais — razão pela qual o 1.1 lia 12:30 como o inteiro 750.
O detalhe é que o software que as pessoas realmente rodam está dividido. O loader padrão do PyYAML e o Psych do Ruby são 1.1; o yaml.v3 do Go e os parsers JavaScript modernos são 1.2. Este conversor aplica o 1.2 e diz a você, pelo nome, cada token em que um leitor 1.1 discordaria — porque a saída útil não é só o JSON, mas o saber de que o arquivo é ambíguo.
Âncoras são expandidas, com um orçamento
&name define uma âncora e *name a referencia. O JSON não tem equivalente, então cada referência é expandida em uma cópia. Essa expansão é o ataque "billion laughs": dez âncoras, cada uma referenciando a anterior duas vezes, expandem para 1,024 nós, vinte para um milhão, trinta para mais de um bilhão. Um arquivo de 200 bytes pode esgotar o heap. A expansão tem um teto de 100,000 nós, e o teto é relatado — que é a diferença entre um erro claro e uma aba travada.
Escalares de bloco mantêm suas quebras de linha
| mantém as quebras de linha, > as dobra em espaços, e o indicador de chomping decide o que acontece com a última: | mantém exatamente uma, |- remove todas, |+ mantém cada uma. Essa última distinção importa para uma chave PEM ou um shell script cuja linha final precisa ser terminada. Um # dentro de um escalar de bloco é conteúdo, não comentário — um parser que o remove come o shebang de todo script.
Chaves duplicadas são relatadas, não escondidas
O YAML diz que chave duplicada é um erro. A maioria dos parsers guarda a última em silêncio. Este guarda a última, igual ao JSON.parse, e diz qual chave e em qual linha — porque uma duplicata em um arquivo de configuração quase sempre é um merge que deu errado.
YAML
regions: [NO, SE] version: "007" retry: 012
JSON
{
"regions": ["NO", "SE"],
"version": "007",
"retry": 12
}
// warning: 012 — leading zero, 1.1 reads it as octalQuais opções e casos-limite o Converter YAML em JSON suporta?
| Parâmetro | Tipo | Padrão | Comportamento e casos-limite |
|---|---|---|---|
| true / false | booleano | resolvidos | Somente essas duas grafias, em qualquer combinação de maiúsculas. Essa é toda a diferença em relação ao YAML 1.1 — e a razão de a Noruega sobreviver. |
| yes / no / on / off / y / n | string | sinalizados | Strings no 1.2, booleanos no 1.1. Cada um é sinalizado pelo nome, para você saber que o arquivo significa coisas diferentes em runtimes diferentes. |
| ~ / null / (vazio) | null | resolvidos | Os três representam um null de JSON. Um valor vazio depois de uma chave é null, não uma string vazia. |
| 012 | inteiro | 12, sinalizado | O 1.2 lê o zero à esquerda como decimal; o 1.1, como octal 10; o autor provavelmente queria a string. Coloque entre aspas para manter o zero. |
| 0o17 / 0x1f | inteiro | 15 / 31 | Octal e hexadecimal explícitos. O 1.2 exige o prefixo 0o para octal, e é por isso que um 017 puro não é 15. |
| .inf / .nan | string | mantidos como texto | O JSON não tem nenhum dos dois, então emitir um deles gera um documento que o JSON.parse rejeita. O token fica como está e é sinalizado. |
| Âncoras e aliases | expandidos | limite de 100,000 nós | Cada *alias vira uma cópia, já que o JSON não tem referências. O limite impede que uma expansão billion-laughs esgote a memória. |
| Chaves de mesclagem (<<) | não suportado | notificado | Rejeitado em vez de implementado pela metade. A semântica de mesclagem interage com sobreposição e ordenação de formas fáceis de errar sutilmente e difíceis de perceber. |
| Multi-documento | separados por --- | array | Vários documentos viram um array JSON. Desligue a opção para converter apenas o primeiro, que é o que um pacote de manifests do Kubernetes geralmente quer. |
| Tamanho da entrada | bytes | 8 MB | A análise roda na thread principal. Acima do teto, a ferramenta recusa em vez de travar a aba. |
Perguntas frequentes
Por que meu `no` é uma string em vez de false?
Porque este parser aplica o esquema core do YAML 1.2, em que só true e false são booleanos. O YAML 1.1 — ainda o que o loader padrão do PyYAML e o Psych do Ruby usam — resolve no, yes, on, off, y e n como booleanos, e é assim que uma lista de códigos ISO de países perde a Noruega em silêncio. Se você quer um booleano, escreva true ou false; se quer a string, você já a tem.
Qual versão do YAML devo assumir que as minhas ferramentas usam?
Verifique em vez de assumir, porque a divisão é real e, na prática, não vem identificada: o safe_load do PyYAML e o Psych do Ruby são 1.1, o gopkg.in/yaml.v3 do Go e a maioria dos parsers JavaScript atuais são 1.2. A resposta confiável é colocar entre aspas tudo o que for ambíguo — um escalar entre aspas é uma string em toda versão de YAML já publicada, o que torna a pergunta irrelevante.
O que aconteceu com as minhas âncoras?
Elas foram expandidas. O JSON não tem como expressar uma referência, então cada *alias se torna uma cópia completa do que a âncora guardava. Isso é sem perdas para os dados e com perdas para a estrutura: o fato de duas partes do documento serem o mesmo objeto se perde. Se você precisa disso preservado, JSON é o alvo errado.
Por que ele se recusou a expandir os meus aliases?
Aliases aninhados se multiplicam. Se cada âncora referencia a anterior duas vezes, trinta níveis expandem para mais de um bilhão de nós a partir de um arquivo que cabe em uma tela — o ataque billion-laughs, que já derrubou serviços de verdade. A expansão para em 100,000 nós e avisa, em vez de crescer até a aba morrer.
Por que meu número mantém as aspas na saída?
Porque você o colocou entre aspas no YAML, e um escalar entre aspas é uma string em toda versão do YAML. Esse é o comportamento correto e geralmente a intenção: version: "007" e version: 007 são valores genuinamente diferentes, e só um deles sobrevive a uma ida e volta exatamente como foi escrito.
Meu YAML é enviado?
Não. O parse e a conversão rodam ambos na aba que você já tem aberta — observe o painel Network enquanto cola. Isso importa especificamente para YAML, porque o YAML que as pessoas precisam converter costuma ser um manifest do Kubernetes, um workflow de CI ou um arquivo docker-compose, ou seja, um arquivo cheio de detalhes de infraestrutura e, às vezes, segredos.