Compare objetos JSON e encontre todas as alterações
Uma comparação textual pode transformar uma pequena atualização JSON em muito ruído, pois recuo, ordem das chaves e formatação escondem as mudanças reais.
Executar grátis
Roda direto no seu navegador. Grátis, sem cadastro — seus dados não são enviados para lugar nenhum.
Esta ferramenta compara valores já interpretados. Ela separa chaves adicionadas, removidas e alteradas, percorre objetos aninhados compartilhados e fornece um caminho JSON Pointer inequívoco. Arrays mantêm a ordem e são comparados por inteiro. A operação é determinística, não acessa a rede e rejeita arrays, valores primitivos ou null como entradas no nível superior.
Como interpretar uma diferença estrutural de JSON
O resultado organiza as diferenças em coleções de itens adicionados, removidos e alterados. Um item adicionado só existe no objeto atualizado; um removido só aparece no original; e um alterado traz os valores anterior e posterior. Cada item usa um caminho JSON Pointer iniciado por barra. Por exemplo, /profile/name identifica name dentro de profile. O formato representa uma barra na chave como ~1 e um til como ~0, evitando ambiguidades com níveis aninhados. As propriedades são percorridas em ordem, gerando respostas estáveis. O bloco counts resume as categorias e o total. Se as três listas estiverem vazias, os objetos são estruturalmente iguais, mesmo que o texto original tivesse outro recuo ou outra ordem de chaves.
Tratamento de objetos aninhados e arrays
Quando a mesma chave contém um objeto nos dois lados, a comparação desce até a propriedade específica que diverge. Se profile existir em ambas as entradas e apenas profile.active mudar, o caminho será /profile/active. Se uma chave inteira existir somente de um lado, ela será registrada uma vez com o valor completo, sem criar um evento para cada descendente. Arrays são valores JSON ordenados e completos: inserir, excluir, reorganizar ou editar um elemento marca a propriedade do array como alterada. Primitivos e null são comparados diretamente. Uma troca de tipo também é informada como alteração. Somente as entradas superiores seguem uma regra mais rígida: before e after precisam ser objetos JSON não nulos.
Uso da diferença em revisões e automações
Envie o objeto original em before e a versão proposta em after. A ferramenta do navegador funciona localmente, enquanto uma chamada de API custa US$ 0,002 e entrega a mesma estrutura determinística. Você pode impedir uma implantação quando uma configuração protegida for removida, validar somente caminhos aprovados ou guardar uma diferença compacta para auditoria. Como formatação e ordem das chaves não criam falsos positivos, o recurso atende configurações, webhooks, flags, permissões e respostas normalizadas. Interprete os caminhos como JSON Pointer e considere também a categoria. Para arrays, você recebe os valores completos e pode aplicar regras específicas depois. Uma entrada superior inválida gera um erro claro, nunca uma diferença vazia enganosa.
Casos de uso
Revisar versões de configuração
Compare a configuração implantada com a candidata e mostre apenas mudanças estruturais, sem ruído de espaços ou ordem.
Auditar a evolução de webhooks
Registre quais campos aninhados surgiram, desapareceram ou mudaram entre dois exemplos normalizados.
Proteger configurações aprovadas
Verifique caminhos no CI e interrompa a implantação se uma opção protegida for removida ou alterada.
Perguntas frequentes
Qual formato de caminho aparece no resultado?
Cada caminho é um JSON Pointer no padrão RFC 6901. Barras em chaves viram ~1 e tils viram ~0.
A ordem das chaves conta como alteração?
Não. Objetos são comparados pelas chaves e valores; outra ordem de serialização não gera diferença.
Como os arrays são comparados?
Eles são valores ordenados comparados por inteiro. Editar, inserir, remover ou reorganizar um elemento marca o array como alterado.
Posso comparar dois arrays no nível superior?
Não. before e after devem ser objetos JSON não nulos; arrays ou primitivos superiores geram erro de entrada.
Quanto custa uma solicitação de API?
A ferramenta web roda localmente sem custo. Cada chamada de API usa o preço-base publicado de US$ 0,002.
Para desenvolvedores — acesso via API
Tudo nesta página está disponível via API. Esta seção é para equipes que querem integrar a ferramenta aos próprios sistemas; quem não precisa disso pode simplesmente usar a ferramenta acima.
Endpoint
Autenticação por token Bearer. Um único POST coloca a tarefa na fila; o resultado chega por webhook ou link assinado.
Chame do seu código
curl -X POST https://api.kit.forhosting.com/data/diff-json-objects \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"before":{"name":"Ada","profile":{"active":true,"score":8},"roles":["reader"]},"after":{"name":"Ada","profile":{"active":false,"score":8,"city":"London"},"roles":["reader","editor"]}}'const res = await fetch("https://api.kit.forhosting.com/data/diff-json-objects", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"before": {
"name": "Ada",
"profile": {
"active": true,
"score": 8
},
"roles": [
"reader"
]
},
"after": {
"name": "Ada",
"profile": {
"active": false,
"score": 8,
"city": "London"
},
"roles": [
"reader",
"editor"
]
}
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/diff-json-objects",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"before": {
"name": "Ada",
"profile": {
"active": true,
"score": 8
},
"roles": [
"reader"
]
},
"after": {
"name": "Ada",
"profile": {
"active": false,
"score": 8,
"city": "London"
},
"roles": [
"reader",
"editor"
]
}
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/diff-json-objects", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"before":{"name":"Ada","profile":{"active":true,"score":8},"roles":["reader"]},"after":{"name":"Ada","profile":{"active":false,"score":8,"city":"London"},"roles":["reader","editor"]}}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"before":{"name":"Ada","profile":{"active":true,"score":8},"roles":["reader"]},"after":{"name":"Ada","profile":{"active":false,"score":8,"city":"London"},"roles":["reader","editor"]}}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/diff-json-objects", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Exemplo de requisição
{
"before": {
"name": "Ada",
"profile": {
"active": true,
"score": 8
},
"roles": [
"reader"
]
},
"after": {
"name": "Ada",
"profile": {
"active": false,
"score": 8,
"city": "London"
},
"roles": [
"reader",
"editor"
]
}
}Exemplo de resposta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.diff_json_objects",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}A API é assíncrona: cada chamada devolve um task_id na hora. Se preferir polling, consulte o status a até 1 requisição por segundo.
Preço
Preço publicado, sem tokens nem créditos escondidos. Tarefa que falha não é cobrada.
Limites
max_mb | 25 |
Erros
| HTTP | Código | O que significa |
|---|---|---|
401 | unauthorized | Token ausente ou inválido. Confira o header Authorization. |
402 | insufficient_balance | Saldo insuficiente para esta tarefa. Faça uma recarga e tente de novo. |
404 | unknown_type | Esse tipo de tarefa não existe. Confira o campo type no catálogo. |
429 | rate_limited | Muitas requisições em pouco tempo. Espere um instante e tente de novo. |