Todo projeto precisa de configuração, e você tem três opções principais: JSON, YAML ou TOML. Usei as três extensivamente, e cada uma me irrita de maneiras diferentes. Aqui vai minha opinião honesta sobre quando usar o quê.

JSON: O soldado universal

Você já conhece JSON. Está em todo lugar. Toda linguagem consegue parseá-lo. Mas sejamos honestos sobre suas fraquezas como arquivo de config:

  • Sem comentários. Você literalmente não pode explicar o que uma configuração faz. Isso é absurdo para um arquivo de configuração.
  • Sem vírgula final. Adicione uma nova linha no final, esqueça a vírgula na linha anterior — config quebrada.
  • Aspas em tudo. Toda chave precisa de aspas duplas: {"port": 8080} em vez de simplesmente port: 8080.

Apesar de tudo, JSON é usado para configuração pelo npm (package.json), TypeScript (tsconfig.json), VS Code (settings.json) e mais. O motivo? Zero ambiguidade. JSON é tão rígido que só existe uma forma de interpretá-lo.

YAML: Bonito mas perigoso

YAML é lindo. Limpo, minimalista, legível. Mas tem armadilhas notórias:

yaml

Esse é o "problema da Noruega" que mencionei no artigo sobre YAML. YAML 1.1 trata NO, YES, ON, OFF como booleanos. Foi corrigido no YAML 1.2, mas muitos parsers ainda usam o comportamento 1.1 por padrão.

E tem a sensibilidade à indentação. Um único espaço deslocado pode mudar completamente o significado do seu arquivo — e a mensagem de erro vai ser terrível.

Dito isso, YAML é o padrão para Docker Compose, Kubernetes, GitHub Actions e Ansible. Se você está no espaço DevOps/cloud, fluência em YAML é obrigatória.

TOML: O especialista em configuração

TOML (Tom's Obvious Minimal Language) foi projetado especificamente para configuração. Ele busca ser óbvio — o que significa que (quase) não há como interpretar um arquivo TOML errado.

Veja como uma config TOML se parece:

toml

O que o TOML faz muito bem: tipos nativos de data/hora (created = 2026-03-08T10:30:00Z), sem problemas de indentação, comentários com #, e uma sintaxe que é genuinamente difícil de errar.

A desvantagem? Estruturas profundamente aninhadas ficam verbosas. TOML é ótimo para configs planas, mas se você precisar de cinco níveis de aninhamento, YAML ou JSON podem ser mais legíveis.

TOML é usado por Rust (Cargo.toml), Python (pyproject.toml), Hugo, e um número crescente de ferramentas.

Minhas recomendações

CenárioEscolhaPor quê
Config gerada por máquinaJSONMais rígido e compatível
DevOps/infraestruturaYAMLO ecossistema espera isso
Configuração de appTOMLComentários + ambiguidade mínima
Configurações simples chave-valorTOMLMais limpo para configs planas
Estruturas aninhadas complexasYAMLMelhor sintaxe aninhada

Conclusão

A mesma config nos três formatos

Ver os mesmos dados nos três formatos realmente destaca as diferenças. Aqui está uma configuração de app simples:

JSON:

json

YAML:

yaml

TOML:

toml

Repare como JSON exige todas aquelas aspas e chaves, YAML é o mais conciso mas depende de indentação, e TOML encontra um meio-termo com cabeçalhos de seção explícitos e sem dependência de indentação.

Erros comuns em arquivos de configuração

YAML: Conversão de tipos acidental. Além do problema da Noruega, YAML também interpreta 3.10 como o número 3.1 (descartando o zero final), e 1_000 como 1000. Se seus valores de config são strings de versão como 3.10, sempre coloque entre aspas: version: "3.10".

JSON: Esquecer que a ordem não importa. Objetos JSON são desordenados pela especificação. Se o processamento da sua config depende da ordem das chaves, você está construindo sobre uma base frágil. Alguns parsers preservam a ordem de inserção, outros não.

TOML: Confusão com arrays de tabelas. TOML usa [[colchetes.duplos]] para arrays de tabelas, o que confunde iniciantes. Veja como definir múltiplos servidores:

toml

Configs específicas por ambiente

Uma área onde os três formatos têm dificuldades é o gerenciamento de sobrescritas específicas por ambiente (dev vs staging vs produção). Soluções comuns incluem:

  • Múltiplos arquivos: config.base.yaml + config.production.yaml com merge profundo
  • Interpolação de variáveis de ambiente: Algumas ferramentas YAML suportam a sintaxe ${DB_HOST}, mas não é padrão
  • Ferramentas externas: Doppler, HashiCorp Vault ou serviços de configuração cloud-native

Pessoalmente, prefiro uma abordagem simples: um arquivo de config com valores padrão sensatos, e variáveis de ambiente para tudo que muda entre ambientes. Os três formatos conseguem ler variáveis de ambiente no nível da aplicação, então o formato de config em si não precisa suportar interpolação.

Popularidade do formato por ecossistema

EcossistemaFormato principalExemplos notáveis
JavaScript/Node.jsJSONpackage.json, tsconfig.json, .eslintrc.json
PythonTOMLpyproject.toml, Cargo.toml (Rust)
DevOps/CloudYAMLdocker-compose.yml, manifests k8s, GitHub Actions
GoTOML/YAMLAmbos amplamente usados, sem padrão único
.NETJSONappsettings.json (substituiu web.config baseado em XML)

Conclusão

Não existe uma única resposta certa. Use JSON quando precisar de máxima compatibilidade. Use YAML quando o ecossistema exigir (Kubernetes não vai começar a aceitar TOML). Use TOML quando quiser comentários e mínimas surpresas.

JSONC e JSON5: JSON com rodinhas

Certo, estivemos criticando o JSON por não suportar comentários e vírgulas finais. Mas aqui está o que ninguém te conta: na verdade existem variantes do JSON que corrigem esses incômodos, e você provavelmente já usou uma delas sem perceber.

Primeiro: JSONC (JSON with Comments). Se você já abriu um tsconfig.json e pensou "espera, tem comentários aqui... eu achava que JSON não permitia comentários?" — pois é, isso é JSONC. É basicamente JSON mas você pode usar comentários de uma linha com // e comentários de bloco com /* */. O VS Code usa JSONC para seus arquivos settings.json, launch.json e keybindings.json. O tsconfig.json do TypeScript também é tecnicamente JSONC, não JSON estrito.

Veja como o JSONC se parece:

jsonc

Depois tem o JSON5, que vai mais longe. JSON5 flexibiliza várias das regras mais rígidas do JSON:

  • Strings com aspas simples: {'name': 'Sarah'} — finalmente!
  • Vírgulas finais: {"a": 1, "b": 2,} — chega de ruído nos diffs
  • Chaves sem aspas (se forem identificadores válidos): {name: "Sarah"}
  • Números hexadecimais: 0xFF
  • Strings de múltiplas linhas com continuação por barra invertida
  • Infinity, -Infinity e NaN como números válidos

JSON5 é ótimo para arquivos de config onde humanos são o público principal. Algumas ferramentas suportam nativamente — por exemplo, o .babelrc do Babel pode ser JSON5. Mas não use JSON5 para respostas de API ou troca de dados. O objetivo do JSON estrito é que todos concordam com o formato. JSON5 é para humanos, não para máquinas.

Minha regra: se uma ferramenta suporta JSONC ou JSON5, use. Literalmente não há desvantagem em ter comentários nos seus arquivos de config. Mas se você está escrevendo uma biblioteca que lê configs, suporte JSON padrão primeiro e JSONC/JSON5 como extras opcionais.

Âncoras e aliases do YAML: Config DRY

Aqui vem o verdadeiro recurso matador do YAML que muitos desenvolvedores nunca descobrem: âncoras e aliases. Eles permitem definir um bloco de config uma vez e reutilizá-lo em todo lugar. Basicamente DRY (Don't Repeat Yourself) para arquivos de config.

Uma âncora é marcada com &nome e um alias a referencia com *nome. Aqui está um exemplo prático com Docker Compose:

yaml

Viu o que aconteceu? Definimos configurações comuns uma vez com &common e as puxamos para três serviços com <<: *common. Sem âncoras, você estaria copiando e colando aquela política de restart e config de logging em cada serviço. E quando precisar mudar a rotação de logs? Um lugar em vez de doze.

Você também pode usar âncoras para valores mais simples — não apenas para maps:

yaml

Agora, as armadilhas. A chave de merge << que torna as âncoras realmente poderosas? Ela não faz parte da especificação YAML 1.2. Era uma extensão de tipo do YAML 1.1, e embora a maioria dos parsers populares ainda a suporte, tecnicamente não é padrão. Então se você estiver usando um parser estrito de YAML 1.2, chaves de merge podem não funcionar.

Além disso, âncoras só funcionam dentro de um único arquivo. Você não pode referenciar uma âncora definida em outro arquivo YAML. E as mensagens de erro quando você erra o nome de um alias? Geralmente algo como "undefined alias" sem nenhum contexto sobre onde a âncora deveria estar. Clássico YAML.

TOML a fundo: Recursos avançados

A maioria das pessoas conhece o básico do TOML — seções com [colchetes], pares chave-valor, comentários com #. Mas o TOML tem alguns recursos genuinamente legais que não recebem atenção suficiente. Deixe-me guiar você por eles.

Chaves com pontos permitem definir estruturas aninhadas sem cabeçalhos de seção:

toml

Isso é útil quando você tem apenas alguns valores aninhados e não quer criar uma seção inteira para eles.

Tabelas inline oferecem uma sintaxe compacta tipo JSON para objetos pequenos:

toml

Use tabelas inline com moderação — elas não podem ocupar múltiplas linhas e ficam ilegíveis rápido se você colocar coisa demais.

Strings de múltiplas linhas vêm em dois sabores, e é aqui que o TOML fica surpreendentemente cuidadoso:

toml

A string básica com aspas triplas (""") processa sequências de escape, enquanto a versão literal (''') trata tudo como texto bruto. Isso é perfeito para padrões regex ou caminhos de arquivo do Windows onde você não quer que barras invertidas sejam interpretadas como escapes.

Tipos nativos de data/hora são algo que nem JSON nem YAML lida tão bem:

toml

Esses são tipos de primeira classe no TOML, não strings fingindo ser datas. Seu parser TOML vai te dar objetos reais de data/hora, não strings que você precisa parsear sozinho.

Por que o Cargo do Rust escolheu TOML? Porque as configs do Cargo são exatamente o ponto ideal para o TOML: moderadamente aninhadas, editadas por humanos, precisam de comentários e se beneficiam de tipagem estrita. Você não quer que suas versões de dependência sejam silenciosamente interpretadas como floats (estou olhando pra você, YAML).

Considerações de segurança

Ok, essa é a seção onde as coisas ficam um pouco assustadoras. Se você está carregando arquivos de config de fontes não confiáveis — ou mesmo se acha que não está — precisa conhecer ataques de deserialização.

O exemplo clássico é o yaml.load() do PyYAML. Em versões mais antigas, essa função de aparência inocente podia executar código Python arbitrário embutido em um arquivo YAML. Não estou brincando. Olha isso:

yaml

Se alguém colocar isso numa config YAML e seu app Python carregar com yaml.load() em vez de yaml.safe_load(), vai literalmente executar esse comando de sistema. Deletar tudo. Instalar um backdoor. O que o atacante quiser.

A correção é simples — sempre use yaml.safe_load() em Python:

python

A documentação do PyYAML agora alerta sobre isso, e versões mais novas mostram um aviso de depreciação se você usar yaml.load() sem especificar um Loader. Mas ainda existem incontáveis tutoriais e respostas do Stack Overflow mostrando a versão insegura. É uma mina terrestre escondida em plena vista.

Depois tem o ataque "billion laughs" (também chamado de bomba XML, mas funciona com YAML também). A ideia é expansão recursiva — você define entidades que referenciam outras entidades, criando crescimento exponencial:

yaml

Cada nível multiplica os dados por 5, então no nível 8 ou 9 você está olhando para gigabytes de dados a partir de poucas linhas de YAML. A maioria dos parsers YAML modernos tem limites de profundidade e expansão para prevenir isso, mas vale a pena saber.

JSON é inerentemente mais seguro porque não tem nenhuma semântica de execução. Não há como embutir código, sem construtores de tipo, sem expansão de entidades. Um parser JSON simplesmente lê dados — strings, números, booleanos, arrays e objetos. Só isso. Essa é uma das vantagens subestimadas da simplicidade do JSON. Quando segurança importa, a falta de recursos do JSON é na verdade um recurso.

TOML também é bastante seguro — não tem capacidades de execução de código nem expansão recursiva. Mas é menos testado em batalha que parsers JSON, então mantenha suas bibliotecas TOML atualizadas.

Resumindo: se você aceita arquivos de config de usuários ou fontes externas, JSON é a escolha mais segura. Se precisa usar YAML, sempre use funções de carregamento seguro e considere rodar um linter YAML para detectar construções suspeitas.

Exemplos reais de arquivos de configuração

Teoria é ótima, mas vamos olhar arquivos de config reais que você vai encontrar na prática. Anotei cada um para destacar padrões específicos do formato.

Workflow do GitHub Actions (YAML):

yaml

É aqui que o YAML realmente brilha. A sintaxe de workflow do GitHub Actions seria dolorosa em JSON — todas aquelas listas aninhadas e a estrutura baseada em indentação se mapeiam naturalmente para YAML. Você também pode ver como comentários ajudam a explicar a estratégia de matrix.

Cargo.toml do Rust (TOML):

toml

Repare como o manifesto do Cargo usa tabelas inline para dependências com features. A sintaxe [[bin]] com colchetes duplos define um array de tabelas — cada entrada [[bin]] adiciona outro alvo binário. TOML mantém isso plano e legível sem jogos de indentação.

package.json (JSON):

json

O clássico. Sem comentários, aspas pra todo lado, mas toda ferramenta do planeta consegue ler. O que faz o package.json funcionar apesar das limitações do JSON é que o schema é tão conhecido — você não precisa de comentários para explicar o que scripts.build faz porque todo desenvolvedor JavaScript já sabe.

.prettierrc (JSON):

json

Config simples de chave-valor plana. Honestamente, ficaria um pouco melhor como TOML (comentários!) ou mesmo JSONC, e o Prettier suporta outros formatos. Mas JSON é o padrão, e para algo tão simples, não faz muita diferença.

Migração entre formatos

Então você decidiu que o formato de config do seu projeto foi um erro e quer mudar. Ou talvez esteja importando config de uma ferramenta que usa um formato diferente. De qualquer forma, você precisa converter entre TOML, YAML e JSON. Te digo, nem sempre é tão suave quanto se espera.

Ferramentas de conversão:

  • yq — O canivete suíço para YAML. Pode converter entre YAML, JSON, TOML e XML. yq -o=json config.yaml te dá saída JSON. É como o jq mas para YAML.
  • toml-cli e taplo — Processadores TOML de linha de comando. Taplo é particularmente bom para formatação e validação de TOML.
  • One-liners em Python — Na hora do aperto, python -c "import yaml, json, sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))" < config.yaml converte YAML para JSON. Não é bonito, mas funciona.
  • Conversores online — Para conversões rápidas pontuais, nossos formatadores podem ajudar. Cole sua config no formatador apropriado, limpe-a e reescreva manualmente no formato alvo.

Quando migrar:

  • Sua equipe continua cometendo erros de indentação YAML nas configs de CI? Talvez mudar para TOML reduza essas dores de cabeça.
  • Precisa de comentários num arquivo de config JSON? Considere migrar para JSONC (se a ferramenta suportar) ou TOML.
  • Está construindo um novo projeto Rust/Python e o ecossistema espera TOML? Não lute contra isso — vá de TOML.

Armadilhas comuns na migração:

O parsing implícito de datas do YAML vai te pegar. Se você tem um valor YAML como release: 2024-03-08, o YAML interpreta isso como um objeto de data, não uma string. Converta para JSON e você pode obter "release": "2024-03-08T00:00:00Z" ou "release": "2024-03-08" dependendo do seu conversor. Sempre teste sua saída.

A tipagem estrita do TOML significa que você não pode ter arrays de tipos mistos. Em JSON e YAML, [1, "two", true] é perfeitamente válido. No TOML, todo elemento de um array deve ser do mesmo tipo. Se seus dados fonte têm arrays mistos, você vai precisar reestruturar.

E aqui está o grande ponto: comentários se perdem. JSON não suporta comentários, então se você converter de TOML ou YAML para JSON, todos os seus comentários cuidadosamente escritos desaparecem. Na direção oposta (JSON para YAML/TOML), você vai querer adicionar comentários manualmente para explicar configurações não óbvias, porque a versão JSON certamente não os tinha.

Mais uma coisa — âncoras e aliases do YAML não têm equivalentes em JSON ou TOML. Se sua config YAML depende de âncoras para config DRY, converter para outro formato significa que você terá que duplicar manualmente esses blocos compartilhados. Isso pode ser uma expansão significativa no tamanho do arquivo para configs complexas.

Experimente você mesmo

Qualquer que seja o formato que você escolher, manter suas configs bem formatadas as torna mais fáceis de revisar e depurar. Nosso TOML Formatter limpa arquivos TOML bagunçados instantaneamente. O YAML Formatter corrige problemas de indentação antes que causem problemas. E o JSON Formatter torna até configs JSON profundamente aninhadas legíveis num piscar de olhos.