Usar JSON como formato de configuração é (na maioria das vezes) um erro.
Não é preferência. Não é estilo. É um erro arquitetural, e um erro bem normalizado.
Essa frase incomoda porque JSON funciona. E em tech, quando algo funciona, a gente tem uma tendência coletiva de parar de perguntar se aquilo faz sentido, e começar a construir religião em cima.
Vamos ser justos, JSON é um sucesso gigantesco. Como formato de transporte, ele é quase imbatível: previsível, determinístico, chato do jeito certo, trivial de parsear, trivial de gerar, e está em todo lugar. Máquina com máquina, JSON é ótimo. O problema começa quando pegamos um formato pensado para ser produzido por computadores, e decidimos que ele também deveria ser escrito, lido, revisado, versionado e mantido por humanos, como se a gente também fosse um computador, só que mais lento.
A gente não é.
E sim, “mas meu editor formata” não é argumento. Isso é tipo dizer que uma cadeira feita de pregos é ok porque você comprou uma calça boa.
Isso não é um ataque ao JSON. É um ataque ao hábito da indústria de usar a ferramenta certa no lugar errado, e depois agir surpresa quando as pessoas que escrevem aquilo começam a odiar a própria vida.
Por que o JSON venceu
JSON não venceu por ser expressivo. Ele venceu por ser limitado, consistente e chato. Isso é uma vantagem enorme quando dois sistemas que não se conhecem precisam trocar dados sem negociar intenção, contexto e interpretação.
É um formato pequeno e fechado. Sem atalhos “criativos”. Sem “ah, mas nesse caso”. Sem semântica mágica. Só primitivos e estrutura. Isso é exatamente o que você quer para contratos. Quando alguém diz “minha API fala JSON”, todo mundo entende na hora qual é o acordo. Sem surpresas. Sem interpretações criativas. Sem debates filosóficos nível YAML sobre o que on significa.
Como formato de transporte, JSON merece todo o respeito que recebe.
Se o arquivo é gerado por máquina, raramente tocado por humanos, e validado por um schema estrito, JSON em disco é aceitável. Meu problema é JSON escrito por humanos fingindo ser um formato amigável de autoria.

Onde tudo começa a dar errado
No momento em que você decide que humanos deveriam “autorizar” JSON, você está dizendo, na prática: “a sintaxe importa mais do que a intenção”. Você não fala isso em voz alta, mas é isso que acontece.
Isso geralmente não vem de maldade. Vem de preguiça travestida de simplicidade: “o sistema consome JSON, então as pessoas devem escrever JSON”. Parece lógico. É também o tipo de lógica que cria dor autoimposta em escala.
JSON exige precisão sintática absoluta para expressar a menor intenção. Uma aspas que faltou, uma vírgula, um colchete, e tudo quebra. Não existe “meio quebrado”. Existe “erro de parse” e acabou a conversa.
Para máquinas, isso é ok. Para humanos, isso é hostil.
E antes que alguém mande um “skill issue”, vai editar uma policy grande de IAM em JSON às 2 da manhã, dar deploy, quebrar produção, e depois volta pra palestrar sobre como “é simples, na verdade”.

JSON é estruturalmente hostil para humanos
Isso não é gosto. É estrutura.
JSON não tem comentários (na especificação). JSON é verboso. JSON te obriga a se repetir. JSON te obriga a se preocupar com vírgulas e aspas mais do que com significado. JSON não tem como expressar intenção, só estrutura. Então as pessoas começam a inventar convenções e superstições:
- “essa chave é opcional, mas só nesse cenário”
- “esse valor é string, mas se comporta como enum, exceto quando não”
- “essa seção está depreciada, mas ainda é obrigatória por motivos”
- “não encosta nesse bloco se você gosta de paz”
E como JSON não carrega contexto, o contexto vaza para fora: README, Confluence, mensagens no Slack, conhecimento tribal, “pergunta pro João”. Sua configuração deixa de ser configuração e vira uma caça ao tesouro.
Quando você vê um JSON grande escrito na mão, ele raramente comunica clareza. Ele comunica resistência. Ele comunica que alguém sofreu, e que a única razão dele ainda existir é porque todo mundo concordou em fingir que isso é normal.
Configuração em JSON é um erro normalizado
Configuração, por definição, é algo que humanos vão ler, escrever, revisar, versionar e discutir em pull requests. Ela carrega intenção. Ela precisa de contexto. Ela se beneficia de comentários. JSON não oferece nada disso, por design.
Então o que acontece? A gente cria esses objetos lindos de 300 linhas cheios de flags minúsculas, onde uma vírgula pode invalidar tudo, e aí joga a “documentação” em outro lugar. Revisar vira doloroso. Mudar vira assustador. E a experiência final é basicamente “funciona, mas funciona movido a rancor”.
Exemplos que todo mundo conhece:
tsconfig.json: não é o pior criminoso, mas é a ilustração perfeita de “JSON escrito por humano que queria comentários desesperadamente”.package.json: scripts, configs de tools, overrides, vira um lixão porque é conveniente, não porque é bom.- Qualquer config de política complexa (permissões, regras, roteamento, workflows): JSON transforma domínio em gerenciamento de pontuação.
E sim, você pode colocar tooling. Pode colocar schema. Pode colocar validator. Pode colocar prettier. Pode fazer uma UI que gera JSON. Percebeu algo? Quanto mais sério o sistema fica, mais você afasta humanos de escrever JSON. Isso não é coincidência. É sua própria arquitetura admitindo a verdade.

O argumento pró-JSON
“Mas JSON é simples. Todo mundo sabe.”
Todo mundo sabe um monte de coisa que é uma ferramenta péssima para certos trabalhos.
Todo mundo sabe regex também. Isso não significa que a gente deveria armazenar regra de negócio como string de regex dentro de um JSON e chamar isso de “configuração”. Familiaridade não é critério de escolha de ferramenta. Adequação ao problema é.
JSON é simples de consumir, não simples de autorar. E essa diferença importa bem mais do que parece.
Formatos de autoria existem por um motivo
Se a config é para humanos escreverem, use um formato pensado para humanos.
TOML existe por um motivo. HCL existe por um motivo. Até YAML existe por um motivo, e sim, YAML tem seus próprios problemas, e qualquer pessoa fingindo que YAML é “limpo” provavelmente nunca debugou um edge case esquisito numa sexta à noite.
Mas o ponto é: formatos de autoria normalmente permitem comentários, são mais legíveis, e reduzem o custo cognitivo de escrever. Eles deixam as pessoas pensarem no domínio primeiro, e na representação depois.
E muita ferramenta “boa” já segue esse padrão:
Humanos escrevem algo expressivo. Máquinas validam e normalizam. JSON só aparece nas bordas, quando precisa viajar, ou quando vira um contrato estrito entre sistemas.
Essa separação não é burocracia. É respeito aos limites humanos.

O pipeline que evita sofrimento desnecessário
Em sistemas bem desenhados, o fluxo costuma ser:
- Humanos autoram algo expressivo, confortável e revisável.
- A máquina valida, transforma, normaliza.
- JSON aparece só quando precisa: transporte, persistência, interoperabilidade.
Se você quer configuração tipada, TypeScript pode ser ótimo, porque tipos e tooling trabalham a seu favor. Se você quer “configuração que pessoas conseguem ler e discutir”, TOML/YAML/HCL ou um DSL pequeno costuma ser uma escolha melhor. Se você quer contrato entre sistemas, JSON ainda é rei.
Esse padrão aparece repetidamente em ferramentas modernas porque funciona. Ele respeita limitações humanas e explora forças das máquinas. Forçar JSON desde o começo corta o caminho saudável e empurra o custo para quem menos deveria pagar.

Hater ou fã?
Eu ainda amo JSON onde faz sentido: contratos, APIs, serialização, comunicação máquina com máquina.
Eu ainda odeio JSON quando alguém espera que eu escreva, revise e mantenha regras complexas nele, como se isso fosse uma experiência humana aceitável.
Isso não é elitismo. Não é trend. Não é teimosia.
É respeito básico por quem tem que lidar com o código.
JSON não precisa ser onipresente para continuar valioso. Ele só precisa ficar no lugar certo.
E esse lugar definitivamente não é entre você e o teclado às 2 da manhã, com o CI falhando, e alguém no Slack perguntando “e aí, alguma atualização?”.