Skip to content

Guia

YAML 1.1 vs 1.2

O bug de YAML mais caro de todos tem um código de país no centro.

Por yamltojsonfree · Publicado em · Atualizado em

O que é o problema Norway

Em YAML 1.1, as palavras sem aspas y, yes, on, n, no e off são booleanos — em maiúsculas, minúsculas ou capitalizadas. Assim, uma lista de códigos de país que contenha a Noruega — NO — torna-se silenciosamente false. Nada falha. O documento é analisado, o deploy tem sucesso, e algures a jusante falta um país numa lista porque um booleano não pode ser chave de um dicionário nem satisfazer uma comparação de strings.

O YAML 1.2, publicado em 2009, removeu isto: só true e false são booleanos, e essas seis palavras são strings comuns. Também abandonou as outras conversões implícitas do YAML 1.1 — 022 já não é o octal de 18, e 12:30 já não é um número em base 60 que vale 750.

O senão é que ambas as versões continuam muito usadas, mais de quinze anos depois. O mesmo ficheiro pode por isso significar duas coisas diferentes consoante a ferramenta que o abre — e é exatamente por isso que o conversor de YAML para JSON deste site usa YAML 1.2 por defeito e assinala cada valor do seu documento que seria lido de forma diferente em 1.1.

Todos os valores que mudam de significado

A mesma fonte, lida por cada versão da especificação.

Fonte YAMLLido como YAML 1.2Lido como YAML 1.1Forma segura
country: NO"NO"falsecountry: "NO"
enabled: yes"yes"trueenabled: true
debug: off"off"falsedebug: false
mode: 0222218mode: "022"
start: 12:30"12:30"750start: "12:30"
version: 1.101.11.1version: "1.10"

Repare na última linha: 1.10 perde o zero final em ambas as versões, porque é analisado como número. As strings de versão devem ir sempre entre aspas.

Que parsers leem que versão

Raramente escolhe uma versão de YAML diretamente — herda-a da biblioteca que as suas ferramentas usam. É mais ou menos assim que o ecossistema se divide:

ParserVersãoNotas
PyYAML (Python)YAML 1.1O padrão da maioria das ferramentas Python, incluindo o Ansible.
ruamel.yaml (Python)YAML 1.2O sucessor mantido do PyYAML; 1.1 disponível como opção.
js-yaml v5 (JavaScript)YAML 1.2O motor que este site usa. Versões anteriores liam 1.1.
go-yaml / sigs.k8s.io (Go)Maioritariamente 1.2O que o Kubernetes usa; mantém alguns comportamentos 1.1 por compatibilidade.
SnakeYAML (Java)YAML 1.1O padrão no carregamento de configuração do Spring Boot.
libyaml (C bindings)YAML 1.1A base de muitos bindings de linguagens, PyYAML incluído.

A consequência prática: um ficheiro escrito de um lado dessa tabela e lido do outro pode mudar valores em silêncio. Se o seu YAML é produzido por Python e consumido pelo Kubernetes — um pipeline muito comum — atravessa a fronteira de versão. Os detalhes ao nível do código estão no guia Converter YAML em JSON em código.

Como escrever YAML seguro em ambas as versões

Três hábitos eliminam toda esta classe de bugs. Ponha entre aspas qualquer string que possa ser confundida com outra coisa — códigos de país, números de versão, valores com zeros à esquerda e tudo o que contenha dois pontos. Escreva booleanos apenas como true e false, nunca yes, on ou os seus parentes. E antes de um ficheiro passar de uma ferramenta para outra, passe-o por um conversor ou validador que reporte valores dependentes da versão — ver o seu YAML como JSON explícito é a forma mais rápida de apanhar um tipo que não pretendia.

Referências

Verifique o seu próprio YAML

Cada valor da tabela acima é assinalado pelo conversor e pelo validador deste site, com o que cada versão produziria. Nada é enviado.