Comparador de JSON
Compara dos documentos JSON y ve qué se añadió, eliminó o cambió. El orden de las claves, la indentación y la minificación no cuentan; nada sale del navegador.
Pega JSON en ambos paneles para compararlos
Comparar los datos, no el texto
Una comparación línea a línea responde a una pregunta sobre la escritura: qué líneas de este archivo no son líneas de aquel. Es la pregunta correcta para la prosa y para el código fuente, y la equivocada para JSON, porque un documento JSON no tiene una única manera correcta de escribirse. Reordena los miembros de un objeto, cambia la indentación o minifica un lado, y todas las líneas cambian mientras los datos no se mueven en absoluto. Esta herramienta compara aquello en lo que se convierten los dos documentos al analizarlos, así que lo que informa es lo que de verdad cambió. Abajo hay un mismo documento escrito dos veces: minificado en la primera línea y luego con formato y con sus miembros en otro orden.
{"name":"checkout","port":8080,"tags":["a","b"]}
{
"port": 8080,
"tags": ["a", "b"],
"name": "checkout"
}Esos dos no comparten ni una línea, y esta herramienta no informa de ninguna diferencia entre ellos: los mismos miembros, los mismos valores, el mismo orden dentro de la lista. La consecuencia práctica es que nunca tienes que reformatear un documento para que la comparación funcione, lo cual significaría cambiar justo aquello que te habías propuesto comparar.
Lo que nunca cuenta como diferencia
Se ignoran cuatro cosas sobre cómo está escrito un documento, y se ignoran sin condiciones. No hay ninguna opción que vuelva a activarlas, porque una herramienta que pudiera hacerlo serían dos herramientas con dos significados que explicar, y quien la usa tendría que saber cuál de los dos produjo la respuesta que tiene delante.
- El orden en que están escritos los miembros de un objeto. {"a": 1, "b": 2} y {"b": 2, "a": 1} contienen los mismos datos, así que un serializador que emita sus claves en otro orden en cada ejecución nunca aparece aquí como un cambio.
- Los espacios en blanco de cualquier clase: la indentación, los saltos de línea, el espacio tras los dos puntos. Un documento minificado y otro con formato que llevan los mismos datos son el mismo documento dos veces.
- Cómo se escribe un número. 1e3 es 1000 y 1.50 es 1.5, porque un número JSON tiene un valor y no una escritura: dos documentos que solo difieran ahí contienen los mismos números, y no se informa absolutamente nada sobre ellos.
- Cómo se escapa un carácter dentro de una cadena. Los seis caracteres \u0041 y la letra A son la misma cadena de un carácter.
Hay dos cosas que parecen pertenecer a esa lista y que deliberadamente no están en ella. El orden de los elementos de una lista es dato — [1, 2] y [2, 1] son documentos distintos — y un miembro cuyo valor es null no es lo mismo que un miembro que no está, así que uno frente al otro se informa en lugar de pasarse por alto en silencio.
Añadido, eliminado, cambiado — y un cambio de tipo
Cada fila del resultado es exactamente de una de tres clases, y entre las tres cubren todo lo que la comparación puede encontrar. Toma estos dos documentos:
{"host":"api.example.com","port":8080,"debug":true}
{"host":"api.example.com","port":"8080","retries":3}- Cambiado en $['port']: el miembro está en los dos documentos y su valor no es el mismo, así que se muestran ambos valores. Este además se marca como cambio de tipo, porque 8080 es un número y "8080" es una cadena.
- Eliminado en $['debug']: el miembro está en el primer documento y no en el segundo.
- Añadido en $['retries']: el miembro está en el segundo documento y no en el primero.
El miembro llamado host está en los dos con el mismo valor, así que no se informa en absoluto. Un cambio de tipo es una propiedad de un cambio y no una cuarta clase de fila: es la deriva que un esquema nota y que una persona que lee dos archivos normalmente no, así que se señala donde ocurre en lugar de dejar que la descubras tú.
Dónde está una diferencia, escrito como una ruta
Cada fila nombra el lugar en el que está, y lo nombra como una ruta dentro del documento y no como un número de línea: un número de línea sería un hecho sobre la escritura, que es justo lo que esta herramienta acaba de ignorar. Las rutas son rutas normalizadas de la RFC 9535, la única escritura que este sitio usa siempre que hay que anotar una ubicación dentro de JSON.
- $ es el documento entero, $['port'] es el miembro llamado port que hay en él, y $['hosts'][1] es el elemento en el índice 1 de la lista que está bajo hosts. Un miembro se escribe siempre entre corchetes y comillas, así que un nombre que contenga un punto, un espacio o un corchete propio no necesita nada especial.
- Una ruta es una consulta que puedes ejecutar. Pégala en el Probador de JSONPath de este sitio junto con el documento al que pertenece y selecciona exactamente ese nodo, que es la manera más rápida de leer una diferencia en su entorno.
- Es una consulta contra el documento en el que el nodo está realmente: la ruta de un miembro añadido se ejecuta sobre el segundo documento y la de un miembro eliminado sobre el primero. Aquí nada nombra nunca un nodo que no esté.
Una fila cambiada puede llevar dos rutas, y eso es el emparejamiento de la sección siguiente asomando: en cuanto una lista ha ganado o perdido un elemento, ese mismo elemento queda en un índice distinto en cada lado. Cuando las dos rutas coinciden — que es casi siempre — solo se muestra una.
Cómo se emparejan dos listas
Dos objetos se comparan miembro a miembro, cosa sencilla porque un miembro tiene nombre. Dos listas no tienen nombres, solo posiciones, y compararlas posición por posición es lo que vuelve ilegible la mayor parte de las comparaciones: inserta un registro al principio de una lista larga y ya nada está donde estaba, así que una comparación que lea la posición como identidad informa de la lista entera como distinta — cierto en un sentido muy estrecho e inútil en todos los demás. Por eso los elementos se emparejan primero, por lo que son y no por un campo que tú designes, y solo se informa de lo que el emparejamiento deja fuera.
{"hosts": ["alpha", "beta", "gamma"]}
{"hosts": ["alpha", "staging", "beta", "gamma"]}Eso es una sola fila: staging se añadió en $['hosts'][1]. Los elementos llamados beta y gamma se corrieron una posición y no se mencionan, porque moverse no es cambiar. Ese mismo emparejamiento es lo que permite que un único campo editado dentro de un elemento de una lista se informe como un cambio en ese campo, y no como si el elemento entero hubiera sido sustituido por otro distinto.
El orden sigue contando, y el emparejamiento no finge lo contrario: [1, 2] frente a [2, 1] vuelve como un 1 eliminado del principio y un 1 añadido después del 2, que es lo que pasó. Dos listas también pueden ser demasiado distintas para que valga la pena emparejarlas, y pasado ese punto la comparación recurre a ir posición por posición y lo dice arriba del resultado, de modo que una respuesta ruidosa queda explicada en vez de resultar misteriosa.
El informe y el árbol
La misma comparación se ofrece en dos presentaciones, y pasar de una a otra no recalcula nada: el árbol se dibuja a partir de la misma lista de diferencias que enumera el informe, así que los dos no pueden discrepar sobre qué cambió ni sobre cuánto hay.
- El informe responde a qué cambió: una fila por diferencia, cada una con su ruta, su clase y su valor en cada lado. Es la vista que conviene repasar cuando quieres la lista entera delante.
- El árbol responde a dónde dentro del documento: los dos documentos fundidos en un solo esquema, con abiertas solo las partes que contienen una diferencia. Cada tramo de hijos consecutivos sin nada dentro se pliega en una línea que dice cuántos representa — el par de la sección anterior se dibuja como cinco filas: el documento, la lista que hay dentro, una línea plegada que vale por un elemento, el elemento añadido y una línea plegada que vale por dos.
- El recuento junto al título del resultado son todas las diferencias que hay. Cuando la lista en pantalla se corta por longitud ese recuento no se mueve, y un control al pie de la lista muestra el resto.
~! $['port'] 8080 -> "8080" - $['debug'] true + $['retries'] 3
Eso es lo que produce el control de copiar para los dos documentos de la tercera sección: una marca para la clase, luego la ruta y luego los valores con una flecha en medio — un más para un miembro añadido, un menos para uno eliminado, una virgulilla para un cambio, y una virgulilla con un signo de exclamación cuando además cambió el tipo. Está escrito con símbolos y no con palabras a propósito, para que un resultado pegado sea el mismo texto en cualquiera de los idiomas del sitio que estuvieras leyendo, y no acorta nada: un valor que la pantalla haya cortado está ahí entero.
Lo que cuesta el análisis, y lo que la herramienta dice en voz alta
Comparar aquello en lo que se convierten dos documentos al analizarlos significa convivir con lo que ese análisis cuesta, y analizar JSON no es una operación sin pérdidas. Eso importa aquí más que en ninguna otra parte de este sitio, porque la respuesta que una herramienta de comparación menos se puede permitir es «ninguna diferencia» entre dos documentos que sí difieren. Por eso el texto de cada panel se lee una segunda vez como texto, y lo que el análisis dejó caer se informa al lado de la comparación en lugar de tragárselo.
- Un nombre de miembro escrito dos veces en el mismo objeto. Solo la copia posterior sobrevive al análisis, así que solo la copia posterior se comparó y la anterior no la vio nadie.
- Un número demasiado largo para sobrevivir como un doble. Dos literales distintos pueden analizarse hasta el mismo valor, y los identificadores son justo donde eso ocurre: 12345678901234567890 y 12345678901234567891 son dos enteros distintos y un solo número analizado, así que la comparación por sí sola llamaría idénticos a dos documentos cuyos identificadores difieren.
{"user": {"id": 1}, "user": {"id": 2}}Ese documento se analiza hasta {"user": {"id": 2}}, y la herramienta lo dice bajo el panel en el que se pegó, con la línea y la columna del primer caso y cuántos hay en total. Ninguna de las dos pérdidas detiene la comparación; las dos se sitúan a su lado. Un documento que no se pueda analizar en absoluto se informa en el mismo sitio, con la posición del problema siempre que haya una que dar, y los dos paneles se leen por separado, de modo que dos documentos rotos producen dos errores a la vez en lugar de uno detrás de otro. Un documento anidado mucho más hondo de lo que un valor se puede dibujar se rechaza sin más, que es un rechazo y no una pestaña colgada.
Por qué nada de lo que pegas sale de esta pestaña
Los dos documentos se quedan en tu navegador. No hay subida, ni petición, ni servidor que pudiera guardar una copia: la comparación es aritmética que se ejecuta dentro de la página que ya cargaste, que es también la razón de que siga funcionando con la red apagada. Eso es lo que hace seguro pegar aquí una respuesta de producción, la ficha de un cliente o una carga firmada.
Tampoco se guarda nada. Recarga la página y los dos paneles están vacíos; no hay historial, ni cuenta, ni nada que borrar después. Lo único que sale alguna vez es lo que tú mismo copies.
Preguntas frecuentes
- ¿Esto ignora el orden de las claves?
- Sí, siempre, y esa es la razón de que la herramienta exista. Dos objetos con los mismos miembros y los mismos valores son idénticos como sea que se hayan escrito, así que un serializador que emita sus claves en otro orden en cada ejecución nunca aparece como un cambio. La indentación, la minificación, cómo se escribe un número y cómo se escapa un carácter se ignoran por la misma razón, y nada de eso es una opción que hubieras podido poner al revés.
- ¿Un miembro con valor null es lo mismo que un miembro que no está?
- No, y no hay ninguna opción para tratarlos igual. {"note": null} frente a {} se informa como $['note'] eliminado. Un campo presente y vacío es una afirmación distinta de un campo que nadie envió — todo lenguaje de esquemas y todo lenguaje con tipos estáticos distingue los dos — así que juntarlos aquí tiraría algo que los documentos están diciendo de verdad.
- ¿[1, 2] y [2, 1] se informan como iguales?
- No. Un array JSON está ordenado, así que dos listas con los mismos elementos en otro orden son dos documentos distintos, y llamarlos iguales sería esta herramienta diciendo algo falso sobre el formato. Lo que obtienes es una eliminación y una adición: el 1 se eliminó del principio y se añadió otra vez después del 2. Los objetos van al revés, porque sus miembros están nombrados y no colocados.
- ¿Qué significa la ruta de cada fila?
- Es dónde está la diferencia dentro del documento, escrito como una ruta normalizada de la RFC 9535: $ es el documento mismo, $['port'] un miembro suyo, $['hosts'][1] el elemento en el índice 1 de la lista que está bajo hosts. También es una consulta que puedes ejecutar: pégala en el Probador de JSONPath de este sitio junto con el documento al que pertenece y selecciona exactamente ese nodo, y ningún otro.
- ¿Por qué una fila mostró dos rutas distintas?
- Porque emparejar dos listas puede dejar el mismo elemento en un índice distinto en cada lado. Compara ["alpha", "beta"] con ["intro", "alpha", "beta!"] y salen dos filas: intro se añadió en $[0], y beta cambió a beta!, que es $[1] en el primer documento y $[2] en el segundo. Cuando las dos rutas coinciden, que es lo habitual, solo se muestra una.
- ¿Qué significa un cambio de tipo en una fila?
- Que el valor no es solo distinto sino otra clase de cosa: un número que pasó a ser una cadena, un valor que pasó a ser null, un objeto que pasó a ser una lista. Un puerto escrito 8080 en un lado y "8080" en el otro es el caso más frecuente, y suele significar que cambió un serializador o un cliente y no los datos. Se marca en la fila porque un valor editado y un contrato que se desvía piden respuestas distintas por tu parte.
- Mis dos documentos parecen idénticos pero uno escribe la misma clave dos veces. ¿Qué pasa?
- El análisis se queda con la copia posterior y descarta la anterior, así que la comparación ve un solo miembro y bien puede no informar de ninguna diferencia. La herramienta lee el texto en bruto por separado justo por eso, y dice, bajo ese panel, que un nombre está escrito dos veces, cuántas en total y dónde está el primero. Esa misma segunda lectura detecta un entero demasiado largo para sobrevivir como un doble, que es la otra manera en que dos documentos que difieren se pueden analizar hasta dos que no.
- ¿Puedo obtener un parche que se pueda aplicar?
- No, y es una decisión y no algo que falte. Un JSON Patch se aplica una operación tras otra, así que los índices que lleva dentro se desplazan mientras se ejecuta; emitir uno es una promesa sobre un programa que ejecutarías contra tus propios datos, cosa mucho más ambiciosa que describir lo que difiere. Lo que sí puedes llevarte es el informe como texto, desde el control de copiar: el mismo en todos los idiomas del sitio y sin acortar en ninguna parte.
- ¿Se envía a un servidor algo de lo que pego?
- No. Los dos documentos se comparan en tu navegador y ninguno sale de él: sin subida, sin petición y sin nada guardado entre visitas. Eso es lo que hace seguro pegar aquí una respuesta de producción, y es la razón de que la herramienta siga funcionando con la red apagada. Recarga la página y los dos paneles vuelven a estar vacíos.
Herramientas relacionadas
- Comparador de textos
Cuando el cambio que quieres ver está en la escritura y no en los datos — una pasada de indentación, una clave que cambió de sitio, o dos archivos que ni siquiera son JSON — la comparación que lo muestra es la de línea a línea. Es justo lo que hace esa página, con opciones de espacios y mayúsculas y un parche copiable.
- Formateador JSON
Valida y embellece JSON, con ubicaciones de error claras.
- Formateador SQL
Formatea y embellece SQL — varios dialectos.
- Formateador XML
Formatea XML y comprueba que está bien formado: embellece o comprime.