Como comparar dois arquivos JSON e encontrar o que mudou
A forma mais rápida de comparar dois arquivos JSON é colar ambos em uma ferramenta de diff lado a lado, formatá-los da mesma forma e ler as linhas que ela destaca. A parte difícil geralmente não é a comparação. É o ruído: chaves reordenadas, indentação diferente e vírgulas finais perdidas podem fazer com que dois arquivos quase idênticos pareçam não compartilhar nada em comum.
Este guia explica como obter um diff limpo e confiável. Vamos analisar por que os arquivos JSON divergem no papel enquanto permanecem iguais em significado, os poucos métodos que vale a pena conhecer, e um exemplo prático que você pode acompanhar. Se você só quer a ferramenta, nossa página de comparação JSON faz tudo isso no navegador.
Por que os arquivos JSON são enganosamente difíceis de comparar
JSON tem uma gramática pequena e estrita (veja a especificação em json.org), mas dá aos autores muita liberdade em como dispõem o texto. Dois arquivos podem descrever exatamente o mesmo objeto e ainda assim diferir byte a byte. Um diff de texto simples não sabe nada disso, então ele sinaliza tudo fielmente.
Eis o que você deve internalizar antes de começar: as chaves de objeto em JSON
não têm ordem. A especificação
(RFC 8259)
define um objeto como um conjunto não ordenado de pares nome/valor. Portanto
{"name":"Ada","id":7} e {"id":7,"name":"Ada"}
são iguais, mesmo que um diff de linhas os pinte de vermelho e verde.
| O que você vê no diff | É uma mudança real? | O que fazer |
|---|---|---|
| Chaves em ordem diferente | Não, objetos não têm ordem | Ordenar as chaves nos dois lados |
| Indentação de 2 vs 4 espaços | Não | Formatar os dois lados da mesma forma |
| Minificado vs pretty-printed | Não | Formatar os dois lados |
| Quebra de linha no final do arquivo | Não | Ignorar, ou remover espaços em branco |
Um valor mudou de "7" para 7 | Sim, string vs número | Investigar, isso é real |
| Itens de array em ordem diferente | Talvez, arrays são ordenados | Decidir se a ordem importa aqui |
Essa última linha pega as pessoas de surpresa. Arrays mantêm sua ordem,
objetos não. Então [1, 2, 3] e [3, 2, 1] são
genuinamente diferentes, mas as chaves dentro de um objeto podem ser
embaralhadas livremente. Se você quiser os detalhes técnicos sobre como
JavaScript analisa tudo isso, o MDN tem uma sólida
referência sobre o objeto JSON.
Quatro formas de comparar JSON e quando usar cada uma
Não existe um único método melhor. Depende de onde os arquivos estão e o que você está tentando descobrir. Veja como as opções mais comuns se comparam.
| Método | Melhor para | Esforço | Entende JSON? |
|---|---|---|---|
| Revisão visual | Arquivos pequenos, um ou dois campos | Baixo | Não, você é o parser |
| Ferramenta diff online | Verificações rápidas, colar de qualquer lugar | Baixo | Com formato + ordenação de chaves, sim |
Linha de comando (jq, diff) | Arquivos em disco, scripts, arquivos grandes | Médio | Sim, quando você ordena primeiro |
IDE ou git diff | Arquivos já em um repositório | Baixo se commitado | Baseado em linhas por padrão |
Para a maioria das pessoas, uma ferramenta de navegador vence em velocidade porque não há nada a instalar e você pode colar um trecho diretamente de um log ou uma chamada de API. O problema é o ruído de formatação, que vamos resolver a seguir. Se você vive no terminal, jq é a ferramenta a aprender, e mostraremos a única flag que importa.
A comparação limpa mais rápida, passo a passo
Esta é a rotina que uso quando alguém me passa dois arquivos de configuração e pergunta "o que é diferente?" Leva cerca de quinze segundos.
- Abra a ferramenta de comparação JSON.
- Cole o original à esquerda e a nova versão à direita.
- Clique em Formatar nos dois lados para que compartilhem a mesma indentação.
- Ative ordenar chaves (canonicalizar) para que chaves reordenadas parem de aparecer como mudanças.
- Leia o resultado. Verde é adicionado, vermelho é removido, e um valor alterado aparece como um de cada.
Os passos três e quatro são todo o segredo. Uma vez que os dois arquivos estão formatados de forma idêntica e suas chaves estão ordenadas, a única coisa restante a destacar é o que realmente mudou. Nosso motor de diff é construído sobre o diff-match-patch do Google, que compara linha por linha primeiro para permanecer rápido mesmo em arquivos longos.
Um exemplo prático
Digamos que você está revisando uma alteração em um registro de usuário. Aqui está o antes:
{
"name": "Ada Lovelace",
"role": "editor",
"active": true,
"seats": 3
}
E aqui está o depois, como um colega entregou para você:
{
"active": true,
"name": "Ada Lovelace",
"role": "admin",
"seats": 5,
"team": "platform"
}
Coloque esses em um diff de linhas bruto e parece que quase todas as linhas se moveram, porque as chaves estão em ordem diferente. Formate e ordene os dois, e a história real é curta:
| Campo | Antes | Depois | Mudança |
|---|---|---|---|
role | editor | admin | Modificado |
seats | 3 | 5 | Modificado |
team | — | platform | Adicionado |
name | Ada Lovelace | Ada Lovelace | Sem mudança |
active | true | true | Sem mudança (só se moveu) |
Três edições reais: uma mudança de função, uma contagem de assentos e um novo
campo de equipe. O reordenamento era ruído. Essa promoção de editor
para admin é o tipo de coisa que você quer detectar na revisão,
e é fácil perder quando está enterrada sob vinte linhas de falsos positivos.
Eliminando o ruído de formatação na linha de comando
Se seus arquivos já estão em disco, a mesma ideia de "formatar e ordenar"
funciona com dois comandos curtos. A flag -S diz ao jq para
ordenar as chaves do objeto; passar ambos os arquivos por ele os normaliza
para que um diff simples seja honesto:
jq -S . old.json > old.sorted.json
jq -S . new.json > new.sorted.json
diff old.sorted.json new.sorted.json
Agora diff reporta apenas valores que realmente mudaram, porque
ambos os arquivos têm a mesma indentação e a mesma ordem de chaves. Este é
o equivalente no terminal de clicar em Formatar e ordenar chaves no navegador.
Diff de texto vs diff estrutural
Tudo acima é um diff de texto: rápido, visual e perfeito para uma
pessoa ler uma mudança. Um diff estrutural vai mais longe e descreve
a mudança como dados. O padrão para isso é JSON Patch, definido na
RFC 6902,
que expressa edições como operações como replace e
add em um caminho específico. Você quer um diff estrutural quando
um programa precisa aplicar a mudança, não apenas uma pessoa revisando
visualmente. Para revisão do dia a dia, um diff de texto com chaves ordenadas
é mais do que suficiente.
Armadilhas comuns para ficar atento
| Armadilha | Por que machuca | Correção |
|---|---|---|
| Precisão de números | Inteiros acima de 2^53 − 1 perdem precisão em JavaScript | Compare IDs grandes como strings; veja MAX_SAFE_INTEGER |
| Escapes Unicode | "café" e "café" são a mesma string, bytes diferentes | Formatar os dois lados, o que normaliza a codificação |
| Chaves duplicadas | A maioria dos parsers mantém silenciosamente a última | Validar o JSON antes de confiar no diff |
| Vírgulas finais | Não são JSON válido; um arquivo pode não ser parseado | Corrigir a sintaxe primeiro, o validador vai sinalizá-la |
| String vs número | "5" e 5 parecem iguais mas são tipos diferentes | Esta é uma mudança real, não a ignore |
Ferramentas relacionadas
JSON raramente é o único formato com que você lida. Se você está comparando configurações entre ambientes, comparar YAML aplica a mesma ideia ao YAML. Revisar mudanças entre duas chamadas de API é para o que o diff de resposta de API foi criado, e atualizações de dependências são mais fáceis de ler na página de diff de package.json.
Perguntas frequentes
- Comparar arquivos JSON online os envia para algum servidor?
- No comparetext.org o diff roda no seu navegador. Os dois arquivos JSON são comparados por JavaScript na sua própria máquina, então nada é enviado para um servidor a menos que você clique explicitamente em Salvar ou Compartilhar. Isso o torna seguro para arquivos de configuração, respostas de API e outros dados que você não gostaria de colar em um site aleatório que faz upload a cada tecla pressionada.
- Por que meus dois arquivos JSON mostram cada linha como diferente?
- Quase sempre é formatação, não mudanças reais. Um arquivo está minificado ou indentado com tabs, o outro com dois espaços, ou as chaves do objeto estão em ordem diferente. Clique em Formatar nos dois lados para que usem a mesma indentação, depois ordene as chaves para que a ordem pare de importar. Depois disso o diff geralmente se reduz ao punhado de valores que genuinamente mudaram.
- Como comparo JSON ignorando a ordem das chaves?
- As chaves de objeto JSON não têm ordem definida, então
{"a":1,"b":2}e{"b":2,"a":1}são iguais. Para fazer um diff de texto concordar, ordene as chaves nos dois lados antes de comparar. No navegador, use a opção canonicalizar (ordenar chaves). Na linha de comando, jq faz isso:jq -S . file.json. Uma vez que os dois arquivos têm as chaves na mesma ordem ordenada, apenas mudanças de valores reais aparecem. - Posso comparar arquivos JSON grandes sem a página travar?
- Sim, até certo ponto. Um diff em modo de linha permanece rápido em arquivos com milhares de linhas porque compara linhas inteiras primeiro em vez de cada caractere. Arquivos muito grandes (vários megabytes) são melhor tratados com uma ferramenta de linha de comando como jq ou git diff, que transmite os dados. Para qualquer coisa que você consiga rolar confortavelmente em um navegador, um diff online é a opção mais rápida.
- Qual é a diferença entre um diff de texto e um diff estrutural de JSON?
- Um diff de texto compara os arquivos linha por linha, da mesma forma que compararia dois ensaios. Um diff estrutural entende JSON, então sabe que uma chave reordenada não é uma mudança e que um valor movido dentro de um array é um movimento, não uma exclusão mais uma adição. Diffs de texto são mais rápidos e suficientes para a maioria das revisões. Diffs estruturais (por exemplo JSON Patch conforme RFC 6902) importam quando você precisa descrever uma mudança como dados que um programa pode aplicar.
- Como comparo duas respostas de API?
- Salve cada resposta em um arquivo ou copie-a da aba de rede do seu navegador, depois cole a resposta antiga à esquerda e a nova à direita. Formate as duas para que a indentação coincida, e ordene as chaves se a API não as retornar em uma ordem estável. A ferramenta api-response-diff é feita exatamente para isso: detectar um campo renomeado, um código de status alterado ou um valor que mudou de string para número entre duas chamadas.
Pronto para experimentar? Cole seus arquivos na ferramenta de comparação JSON e veja o que mudou.