Desenvolvimento

YAML vs JSON: qual escrever e o que cada um faz errado

JSON para o que as máquinas trocam entre si, YAML para o que as pessoas editam. O interessante está na indentação, na conversão de tipos e no código de país que vira false.

Use JSON quando um programa escreve o arquivo e outro programa lê: respostas de API, registros armazenados, qualquer coisa que atravesse uma rede. Use YAML quando quem escreve é uma pessoa que vai ter que entender aquilo de novo dali a seis meses: pipelines de CI, manifests do Kubernetes, Docker Compose, configuração de aplicações. O YAML te dá comentários, strings de várias linhas legíveis e muito menos pontuação. Você paga por isso com uma indentação que carrega significado, uma especificação bem maior e um sistema de tipos que uma hora vai transformar o código de país NO em false. Os dois não são exatamente concorrentes — desde o YAML 1.2, todo documento JSON válido também é YAML válido — então a pergunta de verdade é qual deles você escreve à mão.

Os mesmos dados, dos dois jeitos

Em JSON:

{
  "name": "build",
  "retries": 3,
  "branches": ["main", "release/*"],
  "env": { "NODE_ENV": "production" }
}

Em YAML:

# o build noturno
name: build
retries: 3
branches: [main, "release/*"]
env:
  NODE_ENV: production

Os dois produzem o mesmo objeto. O YAML elimina as chaves, as aspas em volta dos nomes dos campos e todas as vírgulas, e acrescenta um comentário que o JSON não tem como expressar. Repare na linha de branches: aquilo é sintaxe JSON, e continua legal dentro de um arquivo YAML. Misturar os dois estilos é normal, e para listas curtas costuma ser o mais claro.

O que o YAML tem e o JSON não

Comentários. Esse é o grande, e o motivo de quase todo formato de configuração que começou como JSON ter derivado para outra coisa. Um arquivo de configuração sem um lugar para escrever "deixe isto em 3, valores maiores esbarram no rate limiter" é um arquivo de configuração que acumula decisões que ninguém sabe explicar. O criador do JSON tirou os comentários de propósito, porque as pessoas tinham começado a usá-los para carregar diretivas de parsing.

Strings de várias linhas que dá para ler. Um script de shell ou um certificado PEM dentro de JSON vira uma única linha comprida cheia de escapes \n. O YAML tem block scalars: | mantém as quebras de linha exatamente como foram escritas, > junta as linhas em um parágrafo. Os dois removem a indentação em volta, então o texto não leva o layout do seu arquivo para dentro do valor.

Vários documentos em um arquivo. O separador --- deixa um arquivo guardar uma lista de objetos sem relação entre si, que é o motivo de um deployment, um service e um ingress do Kubernetes normalmente virem em um único arquivo YAML. O JSON não tem equivalente; o mais próximo é o JSON Lines, um objeto compacto por linha.

Reaproveitamento. Os anchors e aliases (&defaults e *defaults) deixam você definir um bloco uma vez e apontar para ele depois; as merge keys (<<) encaixam esse bloco dentro de outro mapping. Esse também é o primeiro recurso a dar problema: a maioria das ferramentas não consegue devolver um alias como alias, os parsers discordam sobre a ordem do merge, e alguns poucos aliases aninhados conseguem expandir um arquivo minúsculo em gigabytes de memória — um truque de negação de serviço velho o bastante para ter apelido, a bomba YAML.

O que o JSON tem e o YAML não

Um jeito óbvio de escrever cada coisa. A gramática inteira do JSON cabe em uma única página de diagramas de sintaxe. O YAML tem três jeitos de escrever uma string — simples, entre aspas simples, entre aspas duplas —, dois estilos de block scalar com seus próprios modificadores de quebra final, flow style, block style e um capítulo inteiro de regras sobre onde o espaço em branco pode ficar. Essa flexibilidade é o motivo de duas pessoas editando o mesmo arquivo YAML produzirem diffs que discordam no estilo.

Um parser na biblioteca padrão. Python, JavaScript, Go e todo o resto leem JSON sem instalar nada. YAML quase sempre significa uma dependência, e qual dependência importa, porque os parsers divergem justamente nos casos que mordem.

Espaço em branco que não significa nada. Você pode minificar o JSON, colar num campo de formulário, enfiar numa variável de shell ou mandar por e-mail, e ele sobrevive. Cole YAML em qualquer coisa que reindente e você mudou os dados. É também por isso que JSON é o que trafega pela rede e YAML é o que fica no repositório.

Sem tipagem implícita. No JSON, o que está entre aspas é uma string e o que está sem aspas é um número, true, false ou null. Não há nada a adivinhar. O YAML resolve os escalares sem aspas por padrão de texto, que é a origem de todos os itens da próxima seção.

Onde o YAML morde

O problema da Noruega

O YAML 1.1 tratava yes, no, on e off como booleanos. Então uma lista de códigos de país com um NO sem aspas chega como false, e a chave on: no topo de um workflow do GitHub Actions é, por essas regras, o booleano true e não a palavra. O YAML 1.2 restringiu os booleanos a true e false apenas, mas um monte de parsers ainda se comporta como o 1.1 — o loader padrão do PyYAML entre eles —, então a resposta depende de qual biblioteca lê o seu arquivo. Colocar o valor entre aspas resolve em qualquer versão, e é por isso que arquivos de configuração cuidadosos põem aspas em quase tudo. O conversor deste site usa por padrão a regra do 1.2 e tem uma opção que reprocessa o arquivo com as regras do 1.1. Ativar essa opção é o jeito mais rápido de ver quais dos seus valores sem aspas estão prestes a mudar de significado diante de um parser antigo.

Números que mudam de forma

Escreva version: 1.0 e você recebe o float um, que a maioria dos emissores imprime de volta como 1 e que não bate mais com a string "1.0". Escreva 1.2.3 e, com um ponto a mais, ele continua sendo string. Um ID de 17 dígitos ou mais perde precisão assim que passa por qualquer coisa construída sobre os números do JavaScript, porque o maior inteiro que eles representam com exatidão é 9.007.199.254.740.991. Pelas regras do 1.1, 12:30 era notação de base 60 e chegava como o inteiro 750, que é como uma lista de horários vira uma lista de contagens de minutos. Coloque entre aspas tudo cujo texto exato importe.

A indentação é a sintaxe

Não há chaves para dizer onde um bloco termina, então um valor na margem errada não falha — ele se prende a outro pai e o arquivo carrega do mesmo jeito. Tabs não são apenas desaconselhados como indentação; a especificação proíbe o uso deles, e o erro que você recebe raramente diz isso. Dois espaços por nível é a convenção, e a consistência dentro de um bloco importa mais do que o número que você escolher.

Chaves duplicadas

A especificação considera erro duas chaves iguais no mesmo mapping. Muitos parsers dão de ombros e ficam com a última, então um ajuste acrescentado no fim de um arquivo comprido pode sobrescrever em silêncio essa mesma chave 200 linhas acima. Quando uma mudança parece não ter efeito nenhum, olhe isto primeiro.

Onde o JSON morde

Sem comentários. Sem vírgula final também, o que transforma uma adição de uma linha em um diff de duas linhas e é uma causa comum de um arquivo de configuração não carregar. Nada de NaN ou Infinity. E chaves duplicadas também não são proibidas ali: a RFC 8259 diz que os nomes de um objeto deveriam ser únicos, mas não chega a exigir isso, e os parsers em geral ficam com o último.

O outro custo é a legibilidade em escala. Uma configuração JSON de 400 linhas com tudo entre aspas é difícil de percorrer, e uma minificada é impossível — por isso reindentar o arquivo costuma ser o primeiro passo para ler a resposta de API de outra pessoa, uma técnica que o guia sobre formatar JSON minificado cobre direito.

Uma armadilha pertence aos dois formatos. Um secret em um manifest do Kubernetes parece embaralhado porque está em base64, e base64 é codificação, não criptografia — qualquer pessoa que consiga ler o arquivo consegue ler o segredo.

Convertendo de um para o outro

Uma hora alguma coisa lá na frente só aceita JSON — um validador de schema, o corpo de uma requisição HTTP, um filtro de linha de comando — e o que você tem é YAML. Como o YAML é o superconjunto, esse sentido é quase todo mecânico, e um conversor que roda no navegador faz isso sem o arquivo sair da sua máquina — o que importa aqui, porque arquivos de configuração são exatamente o tipo de coisa que ainda guarda um token que alguém esqueceu de tirar.

O que não sobrevive à viagem é tudo o que o JSON não consegue expressar. Os comentários somem. Os anchors e aliases precisam ser resolvidos em estrutura duplicada, ou recusados — o conversor daqui para com um número de linha em vez de adivinhar. De um arquivo com vários documentos só o primeiro atravessa, e ele te avisa quantos eram. O sentido inverso não precisa de conversor nenhum: um JSON válido já é YAML válido, então dá para jogá-lo num arquivo .yaml como está. Vai parecer JSON até alguém reescrever aquilo em block style, mas nada se perde.

Então, qual dos dois?

Quando alguma coisa lá na frente insiste em JSON, o conversor de YAML para JSON daqui traduz o arquivo no seu navegador e te diz, com número de linha, quais recursos ele se recusa a fingir, em vez de devolver um resultado de aparência plausível. Ele também mostra a contagem de chaves e a profundidade, que é um jeito rápido de confirmar que a estrutura saiu com o formato que você esperava.

Se o arquivo com que você está brigando é dado e não configuração, converter um CSV em JSON tem a própria lista de coisas que a conversão muda em silêncio — zeros à esquerda, datas e aspas soltas sendo as vítimas de sempre.

Perguntas frequentes

YAML é melhor que JSON?

Nenhum dos dois é melhor em geral; eles miram em leitores diferentes. O YAML é melhor para configuração que uma pessoa edita, porque tem comentários, strings de várias linhas e muito menos pontuação. O JSON é melhor para dados que circulam entre programas, porque tem uma única grafia óbvia, nenhum espaço em branco com significado e um parser em toda biblioteca padrão.

JSON é YAML válido?

É. O YAML 1.2 define o formato como um superconjunto do JSON, então qualquer documento JSON válido é lido como YAML com o mesmo valor, e você pode colar um trecho de JSON direto dentro de um arquivo YAML. O contrário não vale: comentários, anchors, block scalars e arquivos com vários documentos não têm equivalente em JSON.

Por que o YAML transforma no em false?

Porque o YAML 1.1 tratava yes, no, on e off como booleanos, e muitos parsers ainda seguem essas regras, incluindo o loader padrão do PyYAML. O YAML 1.2 restringiu os booleanos a true e false apenas. Colocar o valor entre aspas resolve em qualquer versão, e é por isso que códigos de país e números de versão aparecem entre aspas em arquivos de configuração cuidadosos.

Dá para colocar comentários em JSON?

No JSON padrão, não. Não existe sintaxe de comentário e um parser rigoroso vai recusar o arquivo. As saídas de sempre são uma chave de enfeite como "_comment" ou um dialeto como o JSON with Comments, que é o que o Visual Studio Code usa para as próprias configurações. Se comentários importam para você, isso é um argumento a favor do YAML.

YAML é mais lento de processar que JSON?

Normalmente é, e muitas vezes por uma margem larga, porque o YAML tem uma gramática bem mais complicada enquanto os parsers de JSON costumam ser código nativo embutido no runtime. Para um arquivo de configuração lido uma vez na inicialização, não faz diferença. Para milhares de documentos em um loop faz, e é um motivo para converter uma vez e ficar com o JSON.

Última atualização 19 de setembro de 2026