Comparador de JSON

Compara dos JSON por estructura, no por texto: el orden de las claves y la indentación dejan de contar como diferencias. Empareja arrays por id y señala cambios de tipo.

./comparador-json

Opciones

1 añadido1 eliminado2 cambiado1 cambio de tipoArrays emparejados por «id»
RutaOriginalComparado
contacto.email"[email protected]""[email protected]"
contacto.tel"2221234567"
productos[id=1].precio1820
+productos[id=0]{"id":0,"nombre":"Cuernito","precio":22}
Tsucursalesnumber → string3"3"
Compartir

Qué hace esta herramienta

Compara dos documentos JSON por estructura, no por texto. Recorre los dos árboles a la vez y reporta cada diferencia con su ruta (contacto.email, productos[id=2].precio), clasificada en cuatro tipos: añadido, eliminado, cambiado y cambio de tipo.

La consecuencia práctica es que el orden de las claves y la indentación dejan de existir como diferencias, y que lo que queda en pantalla es solo lo que de verdad cambió.

Todo ocurre en tu navegador: puedes pegar respuestas de API con datos reales sin que salgan de tu equipo.

Cómo usarla

  1. Pega el JSON original a la izquierda y el que quieres comparar a la derecha.
  2. Si alguno tiene un error de sintaxis, se te dice la línea, la columna y qué falta.
  3. Lee la tabla de diferencias. Marca mostrar también lo que no cambió si quieres ver el documento completo.

Por qué un diff de texto no sirve para JSON

Es la razón por la que existe esta página. Un diff de líneas —el que usan Git, los editores y el comparador de texto de este mismo sitio— es excelente para código, y contraproducente para JSON:

Estos dos documentos son idénticos:

{ "nombre": "Ana", "edad": 30 }
{ "edad": 30, "nombre": "Ana" }

En JSON un objeto es un conjunto de pares clave-valor sin orden. La especificación lo dice y todos los parseadores lo cumplen. Pero un diff de texto marca las dos líneas enteras como cambiadas, porque los caracteres están en otro sitio.

Y al revés: reformatear un archivo con jq o con el botón de “formatear” del editor no cambia ni un dato, y produce un diff de cientos de líneas.

El resultado es que en cuanto un JSON viene de dos fuentes distintas —dos entornos, dos versiones de una API, un export y un import— el diff de texto es inservible: todo aparece cambiado y no se distingue lo importante.

El problema de los arrays, y cómo se resuelve aquí

Este es el detalle que separa a un comparador útil de uno que no lo es.

Un array sí tiene orden, así que lo natural es comparar el elemento 0 con el 0, el 1 con el 1, y así. Funciona hasta que alguien inserta un elemento al principio:

// antes
[ {"id": 1, "nombre": "Concha"}, {"id": 2, "nombre": "Bolillo"} ]

// después
[ {"id": 0, "nombre": "Cuernito"}, {"id": 1, "nombre": "Concha"}, {"id": 2, "nombre": "Bolillo"} ]

Comparando por posición: el elemento 0 “cambió” de Concha a Cuernito, el 1 “cambió” de Bolillo a Concha, y el 2 es nuevo. Tres diferencias, y ninguna es cierta. Lo único que pasó fue una inserción.

La solución es emparejar por identificador en lugar de por posición. La herramienta busca automáticamente una clave estable entre id, _id, uuid, key, slug, code, sku, email y name, y solo la usa si cumple dos condiciones:

  • está presente en todos los elementos de ambos arrays,
  • y sus valores son únicos dentro de cada array.

Si hay repetidos o falta en alguno, emparejar por esa clave mentiría, así que se vuelve a la comparación por posición. Cuando sí se usa, se te dice cuál se eligió, y las rutas pasan a ser productos[id=0] en vez de productos[2] — que además es una ruta que significa lo mismo mañana, cuando el orden vuelva a cambiar.

Puedes desactivarlo con la casilla de opciones para ver el contraste con tus propios datos.

El cambio de tipo, que va aparte

Cuando una misma ruta tiene 1 en un documento y "1" en el otro, no es un cambio de valor: es un cambio de tipo, y se marca con su propia categoría y su propio color.

La distinción importa porque rara vez es intencionada. Casi siempre significa una de estas tres cosas:

  • Una API empezó a devolver números como cadenas, típicamente al cambiar de ORM o de serializador.
  • Un campo pasó de null a 0, o al revés, y el cliente que lo consume distingue entre “no hay dato” y “el dato es cero”.
  • Una migración a medias dejó unos registros con un formato y otros con otro.

Son diferencias que rompen un cliente aunque el valor “se vea igual” en pantalla. Un diff de texto no las distingue de un cambio cualquiera; aquí saltan a la vista.

Cuándo se usa esto de verdad

  • Comparar la respuesta de una API entre dos entornos (local contra producción, o antes y después de un despliegue) para encontrar el campo que cambió sin querer.
  • Revisar una migración de datos: el volcado de antes contra el de después.
  • Depurar un contrato de API cuando el cliente falla y la respuesta “parece igual”.
  • Comparar dos ficheros de configuración, dos package.json, dos exports de traducciones.
  • Auditar qué cambió una integración de terceros entre dos ejecuciones.

Los tres errores de sintaxis que más aparecen

Son cosas que JavaScript acepta y JSON no, y la herramienta las nombra explícitamente en vez de repetir el mensaje críptico del navegador:

EscritoProblema
{"a": 1,}Coma final antes del cierre. Válida en JS, prohibida en JSON
{'a': 1}Comillas simples. JSON exige dobles
{a: 1}Clave sin comillas. En JS es un objeto válido; en JSON no

La línea y la columna las calcula un analizador propio, no el mensaje de JSON.parse. La razón es concreta: cada motor formatea ese mensaje distinto, y en las versiones actuales de Chrome y Node conviven dos formatos de los cuales solo uno incluye la posición. Un analizador propio devuelve lo mismo en cualquier navegador, y además puede explicar el error en lugar de describirlo.

Preguntas frecuentes

¿En qué se diferencia de comparar dos JSON con un diff de texto?

Un diff de texto compara líneas, y en JSON eso produce ruido constante. Dos documentos con las mismas claves en distinto orden son exactamente el mismo objeto, pero un diff de líneas los marca enteros como cambiados; y reindentar un archivo, que no cambia ni un dato, genera cientos de diferencias falsas. Esta herramienta compara valores por ruta: el orden de las claves y el formato no cuentan, y lo único que se reporta es lo que de verdad cambió.

¿Por qué insertar un elemento en un array lo marca todo como cambiado?

Porque la mayoría de comparadores emparejan los elementos de un array por su posición. Si insertas uno al principio, el que estaba en la posición 0 pasa a la 1, el de la 1 a la 2, y todos aparecen como modificados aunque no hayas tocado ninguno. Esta herramienta detecta si los elementos tienen un identificador estable —`id`, `_id`, `uuid`, `slug`, `code`…— y los empareja por él: entonces una inserción se reporta como una sola inserción. Se puede desactivar con la casilla de opciones para ver la diferencia.

¿Qué es un "cambio de tipo" y por qué se marca aparte?

Es cuando una misma ruta tiene valores de distinta naturaleza en los dos documentos: `1` frente a `"1"`, `null` frente a `0`, un array frente a un objeto. Se marca aparte porque casi nunca es un cambio de dato: suele ser un error de serialización, una API que empezó a devolver los números como cadenas, o una migración a medias. Es el tipo de diferencia que rompe un cliente aunque el valor "se vea igual".

¿Se envían mis JSON a algún servidor?

No. Todo el análisis, el parseo y la comparación ocurren en tu navegador con JavaScript. Los documentos no se suben, no se guardan y no quedan en ningún registro. Puedes comparar respuestas de API con datos reales, configuraciones o volcados de base de datos sin que salgan de tu equipo.

¿Por qué mi JSON da error si a mí me parece correcto?

Los tres motivos más frecuentes son cosas que JavaScript permite y JSON no: la coma final antes de un cierre (`{"a": 1,}`), las comillas simples en vez de dobles (`{'a': 1}`) y las claves sin comillas (`{a: 1}`). Esta herramienta las detecta y te lo dice con esas palabras, además de darte la línea y la columna exactas. La posición la calcula un analizador propio, no el mensaje del navegador, porque cada motor lo formatea distinto y algunos ni siquiera incluyen la posición.

¿Puedo ignorar diferencias que no me importan?

Sí, con tres opciones. Ignorar mayúsculas compara las cadenas sin distinguir caja. Ignorar espacios sobrantes recorta el principio y el final de cada cadena, útil cuando un sistema añade espacios al exportar. Y tratar `1` y `"1"` como iguales sirve contra las APIs que devuelven todos los valores como texto. Esta última no oculta el cambio de tipo, solo evita que se marque además como cambio de valor.

Reseñas y valoraciones

Aún no hay reseñas. ¡Sé la primera persona en opinar!

Escribe una reseña

Tu calificación *