YAML para JSON (e vice-versa)

Cole uma configuração e escolha o sentido. Os erros vêm com a linha certa, e a página diz quais valores um leitor de YAML 1.1 leria de outro jeito: “no” virando false, “22:22” virando 1342.

O texto e os arquivos ficam no seu navegador: a conversão acontece no seu dispositivo e nada é enviado a ninguém.

Por que “no” vira false: o problema da Noruega

O YAML existe em duas versões e as duas estão em uso. 1.1 é de 2005 e é a versão do PyYAML, portanto do Python e do Ansible; 1.2 é de 2009 e é a versão dos leitores mais novos, incluindo o desta página. O texto do arquivo é o mesmo, mas algumas palavras escritas sem aspas são coisas diferentes para as duas versões.

O exemplo que deu nome ao problema é o código da Noruega: em uma lista de países NO é o booleano false para um leitor 1.1, e a Noruega desaparece. Não é o único caso. yes, on e off também são booleanos e, de fato, a chave on: dos workflows do GitHub Actions, lida com o PyYAML, vira true. 0755 é um número octal que vale 493. 22:22, um mapeamento de portas em um docker-compose, é um número de base 60 que vale 1342. No YAML 1.2 todos são texto, exceto 0755, que vira o número 755.

Por isso a página não se limita a converter: para cada valor escrito sem aspas ela pergunta aos dois leitores o que eles veem e, se discordarem, avisa você, com a linha, o valor daqui e o da outra versão. Com o menu Ler o YAML como você escolhe qual leitor imitar. A leitura 1.1 é a do PyYAML, caractere por caractere; a especificação 1.1 também lista y e n entre os booleanos, mas o PyYAML não, e aqui seguimos o PyYAML, porque é o leitor 1.1 que as pessoas realmente têm à mão. A cura, em todos os casos, é a mesma: aspas.

Erros, na linha certa

É o motivo pelo qual quase todo mundo abre um conversor: o programa diz que o arquivo está errado e não diz onde. Aqui cada erro tem um nome, a linha e um trecho com a linha destacada, e o botão Ir para a linha a seleciona na caixa.

Os casos mais comuns têm uma explicação própria. Uma tabulação na indentação, que o YAML não aceita e que parece igualzinha a espaços (no trecho aparece como uma seta); e, na leitura 1.1, também uma depois dos dois-pontos ou no fim da linha, que o YAML 1.2 deixa passar e o PyYAML não. Uma indentação não alinhada com as linhas do mesmo nível. Um valor com dois-pontos seguido de espaço, como título: Roma: um guia, que o YAML toma por uma nova chave. Um apóstrofo dentro de aspas simples, como em 'Don't panic', que fecha o texto no meio. Um valor sem aspas que começa com arroba, como @types/node, ou com uma variável do Ansible, como {{ app_version }}. O espaço que falta depois dos dois-pontos. Uma chave repetida, que o PyYAML aceitaria sem dizer nada, ficando com a última.

O caso mais chato é a aspa deixada aberta: o leitor só percebe várias linhas depois e aponta a linha errada. Aqui a página procura a linha em que a aspa ou o colchete abre sem fechar e destaca essa. A mensagem original do leitor continua logo abaixo, de qualquer forma, para quem quiser.

O que o JSON não sabe dizer, dito

As datas continuam como texto, exatamente como foram escritas, porque o JSON não tem um tipo para datas; a página lista as linhas, porque o PyYAML as transformaria em datas. Os números inteiros acima de 2^53, como um código de pedido de vinte dígitos, são escritos no JSON dígito por dígito, mas a página avisa que um programa JavaScript que os leia de volta os arredonda: 12345678901234567890 viraria 12345678901234567000. Os valores infinito e “não é um número” viram null, e são listados. Números que mudam de forma são sinalizados à parte: 3.10 vira 3.1, que é o mesmo número, mas não a mesma versão do Python.

As tags como !Ref e !Sub do CloudFormation ou !reference do GitLab não existem no JSON: o valor fica, a tag não, e a página lista quais são e onde estão. Vários documentos separados por --- viram uma lista. As âncoras e aliases são expandidos, e aqui há um limite declarado: se a expansão acrescentar mais de 100.000 valores, a conversão para. É a defesa contra o ataque chamado “billion laughs”: dez linhas que, expandidas, viram um bilhão de valores e travam qualquer programa que as leia até o fim.

JSON para YAML: as aspas que realmente são necessárias

No sentido contrário, o risco se inverte. Um texto como "no", "010" ou "12:30" é claramente um texto no JSON; escrito em YAML sem aspas, qualquer leitor 1.1 o transforma em booleano ou número. Aqui todo texto que pelo menos um dos dois leitores leria como outra coisa vai entre aspas, e a página diz quais.

Escolha a indentação, dois ou quatro espaços, ou a forma compacta em uma única linha. Se o JSON for uma lista, você pode transformá-la em vários documentos YAML separados por ---, como se faz com os arquivos do Kubernetes. E se o JSON não puder ser lido, o erro também tem nome aqui: a vírgula sobrando antes do colchete, aspas simples, o comentário, a chave sem aspas. O leitor de JSON foi escrito de propósito, em vez de usar o do navegador, que arredonda inteiros grandes e aponta o erro de um jeito diferente em cada navegador. Para arrumar um JSON sem mudar de formato, indentando-o ou ordenando suas chaves, existe o Formatador e validador de JSON.

Como foi testada

O juiz não é esta página: é o PyYAML, o leitor de YAML do Python, usado de duas maneiras. Como está, ele dá a leitura 1.1; com as regras do Core Schema reescritas a partir do texto da especificação 1.2, ele dá a leitura 1.2. Em 500 documentos gerados ao acaso, cheios das armadilhas acima, com âncoras, merges e vários documentos, os valores da página devem coincidir com os dele nas duas leituras, e a lista de linhas sinalizadas deve ser exatamente a lista de linhas em que as duas leituras do PyYAML discordam, nem uma a mais nem uma a menos. O mesmo vale para as tabulações: em 600 documentos com uma tabulação inserida ao acaso, a leitura 1.1 da página aceita e rejeita exatamente os mesmos que o PyYAML aceita e rejeita, e, quando para por causa da tabulação, aponta a mesma linha e a mesma coluna.

No sentido contrário, 400 estruturas JSON geradas ao acaso, escritas com três indentações diferentes, fazem o caminho completo: de JSON para YAML e de volta para JSON, e no final devem voltar idênticas. No meio, o YAML produzido é lido de novo pelo PyYAML nas duas versões e deve dar os mesmos dados do JSON de partida. Por fim, o leitor de JSON é comparado com o módulo json do Python em 1.200 textos estragados de propósito: devem aceitar e rejeitar os mesmos e apontar a mesma linha.

O que ela não faz

Ela não mantém os comentários. O JSON não os tem, então ao passar de YAML para JSON eles desaparecem, e na volta não reaparecem. Ela não verifica se o arquivo é uma configuração válida para o programa que vai lê-lo: só o docker sabe se um docker-compose tem os campos certos. Ela não converte as tags do CloudFormation na forma longa usada no JSON desse serviço: ela as remove e avisa. Ela não adivinha todas as codificações: lê UTF-8 e UTF-16, e um arquivo salvo em outra é lido como Windows-1252, avisando.

Ela não converte outros formatos. Para XML existe o XML para JSON e vice-versa, para transformar uma lista JSON em tabela existe o JSON para CSV, e se o arquivo YAML está dentro de uma resposta do ChatGPT ou do Claude, para extraí-lo limpo existe o Extrair código da IA.

Ferramentas relacionadas