Como comparar dois JSON ignorando a ordem das chaves
Dois JSON podem ter o mesmo conteúdo e textos diferentes: basta mudar a ordem das chaves ou os espaços. Por isso a comparação certa é feita nos dados, não no texto. Este guia mostra como listar as diferenças entre dois JSON em JavaScript e Python, como compará-los em PHP e as pegadinhas de tipo de cada linguagem, como true igual a 1.
Por que não comparar o texto
{"a":1,"b":2} e { "b": 2, "a": 1 } têm o mesmo conteúdo, mas textos diferentes. Comparar com JSON.stringify(a) === JSON.stringify(b) também falha, porque a ordem das chaves se mantém no texto gerado. O caminho é ler os dois e comparar os valores, campo a campo.
Para ver as diferenças na hora, cole os dois no comparador de JSON, que lista o que foi adicionado, removido e alterado, com o caminho de cada campo.
As regras da comparação
- Em objetos, a ordem das chaves não importa: o JSON não dá significado a ela.
- Em listas, a ordem importa:
[1, 2]e[2, 1]são diferentes. Se no seu caso a ordem não importar, ordene as duas listas antes (por um identificador, por exemplo). - Tipos contam:
"1"(texto) é diferente de1(número), etrueé diferente de1. nullé diferente de uma chave ausente:{"a": null}e{}não são iguais.
Listar as diferenças em JavaScript
A função percorre os dois valores juntos e anota cada diferença com o caminho no estilo $.usuario.tags[1]. Para só saber se são iguais, no Node.js existe util.isDeepStrictEqual(a, b), que também ignora a ordem das chaves.
// Lista as diferenças entre dois valores JSON já lidos com JSON.parse.
// A ordem das chaves não conta; as listas são comparadas posição a posição.
function diffJSON(a, b, caminho = '$', saida = []) {
const ehObjeto = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
if (ehObjeto(a) && ehObjeto(b)) {
for (const k of new Set([...Object.keys(a), ...Object.keys(b)])) {
const p = `${caminho}.${k}`;
// Object.hasOwn, e não "k in b": com in, uma chave toString existiria em todo objeto
if (!Object.hasOwn(b, k)) saida.push({ caminho: p, tipo: 'removido', antes: a[k] });
else if (!Object.hasOwn(a, k)) saida.push({ caminho: p, tipo: 'adicionado', depois: b[k] });
else diffJSON(a[k], b[k], p, saida);
}
} else if (Array.isArray(a) && Array.isArray(b)) {
for (let i = 0; i < Math.max(a.length, b.length); i++) {
const p = `${caminho}[${i}]`;
if (i >= b.length) saida.push({ caminho: p, tipo: 'removido', antes: a[i] });
else if (i >= a.length) saida.push({ caminho: p, tipo: 'adicionado', depois: b[i] });
else diffJSON(a[i], b[i], p, saida);
}
} else if (a !== b) {
saida.push({ caminho, tipo: 'alterado', antes: a, depois: b });
}
return saida;
} Em Python
Em Python, == entre dicionários já ignora a ordem das chaves. A pegadinha é que True == 1 também é verdadeiro, então {"a": true} e {"a": 1} pareceriam iguais. A função abaixo trata esse caso e devolve o mesmo resultado da versão em JavaScript.
def _iguais(a, b) -> bool:
# No Python, True == 1. No JSON, true e 1 são valores diferentes
if isinstance(a, bool) or isinstance(b, bool):
return type(a) is type(b) and a == b
return a == b
def diff_json(a, b, caminho: str = "$", saida: list | None = None) -> list:
"""Diferenças entre dois valores lidos com json.loads (ordem das chaves não conta)."""
saida = [] if saida is None else saida
if isinstance(a, dict) and isinstance(b, dict):
for k in list(a) + [k for k in b if k not in a]:
p = f"{caminho}.{k}"
if k not in b:
saida.append({"caminho": p, "tipo": "removido", "antes": a[k]})
elif k not in a:
saida.append({"caminho": p, "tipo": "adicionado", "depois": b[k]})
else:
diff_json(a[k], b[k], p, saida)
elif isinstance(a, list) and isinstance(b, list):
for i in range(max(len(a), len(b))):
p = f"{caminho}[{i}]"
if i >= len(b):
saida.append({"caminho": p, "tipo": "removido", "antes": a[i]})
elif i >= len(a):
saida.append({"caminho": p, "tipo": "adicionado", "depois": b[i]})
else:
diff_json(a[i], b[i], p, saida)
elif not _iguais(a, b):
saida.append({"caminho": caminho, "tipo": "alterado", "antes": a, "depois": b})
return saida Com 1 e 1.0, a função considera iguais, como o JavaScript.
Em PHP
No PHP, == compara arrays de forma frouxa, e "1" == 1 é verdadeiro. O === é estrito, mas exige as chaves na mesma ordem. A solução é ordenar as chaves dos objetos e então usar ===:
<?php
// Compara dois JSON pelo conteúdo, ignorando a ordem das chaves dos objetos
function jsonIguais(string $a, string $b): bool
{
$ordenar = function ($v) use (&$ordenar) {
if (!is_array($v)) {
return $v;
}
$v = array_map($ordenar, $v);
if (!array_is_list($v)) {
ksort($v, SORT_STRING); // objeto: ordena as chaves; lista: mantém a ordem
}
return $v;
};
$va = $ordenar(json_decode($a, true, 512, JSON_THROW_ON_ERROR));
$vb = $ordenar(json_decode($b, true, 512, JSON_THROW_ON_ERROR));
return $va === $vb; // === e não ==: com ==, "1" seria igual a 1
} Com json_decode em modo array, {} e [] viram o mesmo array vazio. Aqui 1 e 1.0 são diferentes.
Cuidados
- Números grandes: no JavaScript, inteiros acima de 9007199254740991 perdem precisão no
JSON.parse, e dois IDs diferentes podem parecer iguais. Trafegue IDs grandes como texto. - Datas em texto (
"2026-01-01"e"2026-01-01T00:00:00Z") são textos diferentes, mesmo que representem o mesmo dia. Normalize antes, se for o caso. - Para aplicar as diferenças em outro lugar, existe um formato padrão: o JSON Patch (RFC 6902) descreve mudanças como operações de adicionar, remover e substituir.
- Em testes automatizados, prefira a comparação profunda da biblioteca de testes (como
toEqualno Jest e no Vitest), que mostra onde está a diferença.
Achou um erro neste guia? Avise por e-mail.
Ferramentas para usar junto
Perguntas frequentes
Como comparar dois JSON ignorando a ordem das chaves?
Leia os dois textos (JSON.parse, json.loads ou json_decode) e compare os valores, não o texto. Em Python, == entre dicionários já ignora a ordem. No JavaScript, use uma função de comparação profunda ou util.isDeepStrictEqual no Node.js.
A ordem dos itens de uma lista importa na comparação?
Sim. No JSON, uma lista é ordenada, então [1, 2] e [2, 1] são diferentes. Se a ordem não tiver significado no seu caso, ordene as duas listas antes de comparar.
Por que {"a": true} parece igual a {"a": 1} no Python?
Porque no Python o tipo bool é um tipo de número, e True == 1. Para comparar como o JSON, confira também se os dois valores são do mesmo tipo quando um deles for booleano.
Qual a diferença entre == e === ao comparar JSON no PHP?
O == é frouxo: considera "1" igual a 1 e ignora a ordem das chaves. O === é estrito nos tipos, mas exige a mesma ordem. Ordene as chaves e use ===.
Outros guias
- Como formatar e validar JSON em JavaScript, Python e PHPComo deixar JSON legível e descobrir o erro de um JSON inválido em JavaScript, Python e PHP, com os erros mais comuns e as diferenças entre as linguagens.
- Como comparar dois textos (diff) no terminal e em códigoComo comparar textos e arquivos com diff e git diff, ler o formato unificado e gerar diferenças em JavaScript e Python, com os erros de quebra de linha.