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.

Parece uma mudança, mas geralmente não é
O que você vê no diffÉ uma mudança real?O que fazer
Chaves em ordem diferenteNão, objetos não têm ordemOrdenar as chaves nos dois lados
Indentação de 2 vs 4 espaçosNãoFormatar os dois lados da mesma forma
Minificado vs pretty-printedNãoFormatar os dois lados
Quebra de linha no final do arquivoNãoIgnorar, ou remover espaços em branco
Um valor mudou de "7" para 7Sim, string vs númeroInvestigar, isso é real
Itens de array em ordem diferenteTalvez, arrays são ordenadosDecidir 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étodoMelhor paraEsforçoEntende JSON?
Revisão visualArquivos pequenos, um ou dois camposBaixoNão, você é o parser
Ferramenta diff onlineVerificações rápidas, colar de qualquer lugarBaixoCom formato + ordenação de chaves, sim
Linha de comando (jq, diff)Arquivos em disco, scripts, arquivos grandesMédioSim, quando você ordena primeiro
IDE ou git diffArquivos já em um repositórioBaixo se commitadoBaseado 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.

  1. Abra a ferramenta de comparação JSON.
  2. Cole o original à esquerda e a nova versão à direita.
  3. Clique em Formatar nos dois lados para que compartilhem a mesma indentação.
  4. Ative ordenar chaves (canonicalizar) para que chaves reordenadas parem de aparecer como mudanças.
  5. 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:

O que realmente mudou
CampoAntesDepoisMudança
roleeditoradminModificado
seats35Modificado
teamplatformAdicionado
nameAda LovelaceAda LovelaceSem mudança
activetruetrueSem 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

ArmadilhaPor que machucaCorreção
Precisão de númerosInteiros acima de 2^53 − 1 perdem precisão em JavaScriptCompare IDs grandes como strings; veja MAX_SAFE_INTEGER
Escapes Unicode"café" e "café" são a mesma string, bytes diferentesFormatar os dois lados, o que normaliza a codificação
Chaves duplicadasA maioria dos parsers mantém silenciosamente a últimaValidar o JSON antes de confiar no diff
Vírgulas finaisNão são JSON válido; um arquivo pode não ser parseadoCorrigir a sintaxe primeiro, o validador vai sinalizá-la
String vs número"5" e 5 parecem iguais mas são tipos diferentesEsta é 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.