# 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.

- Endereço oficial: https://pradev.com.br/guias/como-comparar-dois-json
- Tipo: Guia
- Publicado em: 2026-09-30
- Atualizado em: 2026-09-30
- Autor: Leonardo Gaertner (https://pradev.com.br/sobre)
- Ferramentas: [Comparador JSON](https://pradev.com.br/comparador-json)

## 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](https://pradev.com.br/comparador-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 de `1` (número), e `true` é diferente de `1`.
- `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.

```javascript
// 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;
}
```

_JavaScript_

## 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.

```python
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
```

_Python. 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
<?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
}
```

_PHP. 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 `toEqual` no Jest e no Vitest), que mostra onde está a diferença.

## 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 ===.

## Fontes

- [RFC 8259: o formato JSON](https://www.rfc-editor.org/rfc/rfc8259)
- [RFC 6902: JSON Patch](https://www.rfc-editor.org/rfc/rfc6902)

## Guias relacionados

- [Como formatar e validar JSON em JavaScript, Python e PHP](https://pradev.com.br/guias/como-formatar-e-validar-json): Como 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ódigo](https://pradev.com.br/guias/como-comparar-textos-diff): Como 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.
