YAML para JSON
Streams multidocumento e uma chave para a armadilha dos booleanos do YAML 1.1.
Nada do que você cola sai do seu navegador. A lista de permissões connect-src transforma isso em uma garantia do navegador, e não em uma promessa. Confira você mesmo
Converta YAML para JSON, com suporte a múltiplos documentos e uma chave para as regras de tipagem que mais causam confusão.
É nesta direção que as coisas dão errado, e quase tudo se resume a qual versão de YAML as suas outras ferramentas implementam.
O problema da Noruega, demonstrado
No YAML 1.1 as palavras soltas no, yes, on, off, y e n são booleanos. Então uma lista de países contendo NO para a Noruega é lida como false. No YAML 1.2 são strings comuns.
Isso importa porque a divisão atravessa o ecossistema inteiro. PyYAML, o Psych do Ruby e várias ferramentas antigas implementam 1.1. js-yaml, o yaml.v3 do Go e a maioria dos parsers modernos implementam 1.2. O mesmo arquivo significa coisas diferentes dependendo de quem lê.
Aqui você pode trocar as regras de tipagem e ver um valor mudar na sua frente. Medido com js-yaml 5.4.1: `a: no` dá a string "no" no YAML 1.2 e o booleano false no YAML 1.1. Mesmo no modo 1.2, esta ferramenta avisa quando vê um no ou um yes sem aspas, porque a próxima ferramenta do seu pipeline pode não concordar com ela.
As outras coisas que o YAML tem e o JSON não
- Comentários
- Perdidos, para sempre. O JSON não tem sintaxe de comentário. Se você mantém o YAML à mão, esta é uma conversão de mão única.
- Âncoras e aliases
- São expandidos no lugar. Um documento que usa uma âncora cinco vezes vira cinco cópias no JSON, que pode ficar bem maior.
- Timestamps
- O YAML resolve escalares com cara de data para datas de verdade. O JSON não tem tipo data, então elas são escritas como strings ISO 8601. Escolha as regras de tipagem JSON para que fiquem como strings simples desde o começo.
- Chaves que não são strings
- O YAML permite um número ou até uma sequência como chave de mapping. O JSON não, então elas viram strings.
- .inf e .nan
- Sem equivalente em JSON, então viram null.
- Vários documentos
- Um stream separado por --- contém vários documentos. Por padrão o primeiro é convertido e você é avisado de que havia mais; ligue "todos os documentos" para receber um array.
Tabulações
O YAML proíbe tabulações para indentação, de forma absoluta e sem exceções. É o erro de YAML mais comum que existe, e acontece porque algum editor está configurado para inserir tabulações. Esta ferramenta avisa sobre tabulações antes mesmo de tentar fazer o parsing, já que a mensagem resultante de qualquer parser não ajuda em nada.
How to do this in code
Convertendo em código, e o argumento de segurança que vem junto.
py Python
O PyYAML implementa YAML 1.1, então é aqui que "no" vira False.
import yaml, json
# safe_load, never load. yaml.load can construct arbitrary Python
# objects and has been a real remote-code-execution vector.
data = yaml.safe_load(text)
print(json.dumps(data, indent=2, default=str))
# default=str handles the datetime objects PyYAML produces for
# date-shaped scalars, which json.dumps otherwise refuses. sh Shell
yq -o=json eval . input.yaml > output.json
# Every document of a multi-document stream
yq -o=json eval-all '[.]' input.yaml js JavaScript
O js-yaml implementa YAML 1.2, então aqui "no" continua sendo string.
import { load, loadAll } from 'js-yaml';
const data = load(text); // YAML 1.2 core schema
const docs = loadAll(text); // multi-document stream go Go
import "gopkg.in/yaml.v3"
var v any
if err := yaml.Unmarshal(data, &v); err != nil { return err }
out, _ := json.MarshalIndent(v, "", " ") Perguntas frequentes
- Por que o meu valor virou true ou false?
- Você está lendo com um parser de YAML 1.1, onde no, yes, on, off, y e n são booleanos. Ponha o valor entre aspas, ou use um parser de YAML 1.2. Troque as regras de tipagem acima para ver a diferença no seu próprio documento.
- Para onde foram os meus comentários?
- O JSON não tem comentários, então eles são descartados. Não há como contornar. Se o YAML é um arquivo que você mantém, guarde-o como fonte da verdade e gere o JSON a partir dele.
- Por que yaml.load é inseguro em Python?
- Porque ele pode instanciar objetos Python arbitrários a partir de tags no documento, o que torna fazer parsing de YAML não confiável equivalente a executá-lo. Use sempre safe_load.