JSON Toolkit

JSON binario: elegir entre MessagePack, CBOR y BSON

En resumen: MessagePack, CBOR y BSON comprimen JSON en bytes. Compara el coste en bytes, el manejo de int64 y binarios, y obtén una línea clara sobre cuándo merece la pena cambiar.

Intermedio~10 min de lecturaPublicado el 2026-10-31Actualizado el 2026-10-31
Portada que compara los formatos binarios MessagePack, CBOR y BSON

En resumen: mantén el JSON de texto para el intercambio externo y para los datos que las personas necesitan inspeccionar, y cambia a MessagePack o CBOR en enlaces internos solo cuando los payloads binarios, los enteros más allá de 2^53 o los decimales exactos hagan que el tamaño comprimido o la expresividad de tipos sea un problema real; BSON pertenece al ecosistema MongoDB.

El JSON de texto ahorra espacios en blanco; los formatos binarios ahorran la puntuación y la forma textual de los números. Los nombres de campo siguen apareciendo una vez por registro, así que calcula el ahorro real antes de cambiar.

1. Qué ahorra realmente el JSON binario

Fija primero las expectativas. Ninguno de estos formatos es "otra sintaxis de JSON". Codifican el mismo modelo de datos en bytes: objetos, arrays, cadenas, números, booleanos y null. Lo que eliminan es concreto:

  • Caracteres estructurales como comillas, dos puntos, comas y llaves;
  • La forma textual decimal de los números, así que 32 se convierte en un solo byte;
  • El reescaneo para encontrar límites de cadena, sustituido por un prefijo de longitud fija;
  • La codificación Base64 de payloads binarios, que pueden guardarse directamente como bytes.

Lo que no pueden eliminar es igual de concreto: los nombres de campo siguen apareciendo como cadenas en cada registro. Un map de MessagePack, un map de CBOR y un documento BSON repiten la clave en cada entrada. Así que cuando tu JSON son diez mil registros con la misma forma, la diferencia de tamaño comprimido entre texto y binario es mucho menor de lo que sugiere la intuición, porque gzip es mejor eliminando nombres de campo repetidos.

2. De dónde vienen los tres formatos

Formato Especificación y año Origen Uso típico
MessagePack especificación de msgpack.org, desde 2008 Diseño independiente centrado en el minimalismo Valores de caché, IPC, pipelines de logs
CBOR RFC 8949 (STD 94), 2020 Influido por MessagePack, estandarizado por el IETF COSE, WebAuthn, CWT, dispositivos limitados
BSON bsonspec.org, ecosistema MongoDB Diseñado para documentos de base de datos Almacenamiento y protocolo de red de MongoDB

CBOR es el más estandarizado: un media type application/cbor registrado en IANA, reglas de codificación determinista y CDDL para describirlo. MessagePack es el más ligero, con una especificación que cabe en una página. BSON es el más pesado: incorpora ObjectId, Decimal128, fechas y subtipos binarios en su sistema de tipos, y por eso solo es realmente popular dentro del ecosistema MongoDB.

3. Los mismos datos, cuatro codificaciones

Tomemos {"name":"joe"} como ejemplo. Los costes en bytes son fáciles de comparar:

Codificación Bytes Secuencia de bytes
Texto JSON 14 7b 22 6e 61 6d 65 22 3a 22 6a 6f 65 22 7d
MessagePack 9 81 a3 6e 61 6d 65 a3 6a 6f 65
CBOR 10 a1 64 6e 61 6d 65 63 6a 6f 65
BSON 19 longitud total de 4 bytes + byte de tipo + name\0 + longitud del valor de 4 bytes + joe\0 + terminador

Separa los nueve bytes de MessagePack:

  • 81: el nibble alto 1000 significa map, el nibble bajo 0001 significa un par clave-valor;
  • a3: los tres bits altos 101 significan una cadena de longitud fija igual a 3;
  • 6e 61 6d 65: ASCII de name;
  • a3: otra cadena de longitud 3;
  • 6a 6f 65: joe.

El a1 de CBOR es el tipo mayor 5 (map) con longitud 1, y 64 es el tipo mayor 3 (cadena de texto) con longitud 4, así que la semántica es casi isomorfa a la de MessagePack. BSON es más grande: cada documento lleva una longitud total de 4 bytes, cada campo repite un byte de tipo y su nombre, y cada cadena repite una longitud más un \0 final. En documentos pequeños, BSON puede ser fácilmente más grande que el texto JSON.

Puedes comprobar los prefijos directamente representando esos bytes como hexadecimal:

const messagePackBytes = [0x81, 0xa3, 0x6e, 0x61, 0x6d, 0x65, 0xa3, 0x6a, 0x6f, 0x65];
const hexText = messagePackBytes.map((byte) => byte.toString(16)).join(' ');
console.log(hexText); // 81 a3 6e 61 6d 65 a3 6a 6f 65

3.1 Tamaño y velocidad de parseo: ignora los números de marketing

Las afirmaciones de que lo binario es "10 veces más rápido" deberían dividirse en dos preguntas.

Tamaño. Sin comprimir, lo binario es más pequeño porque desaparecen la puntuación y los espacios en blanco. Pero los pipelines reales casi siempre comprimen: tras gzip o brotli, los nombres de campo repetidos se comprimen, y la ventaja binaria se reduce drásticamente. Sigue el método de Minificación de JSON frente a gzip: mide primero los bytes comprimidos y luego decide si un cambio de formato merece la pena.

Velocidad de parseo. Lo binario se salta el lexing (escanear comillas, comas y caracteres de números), así que en teoría debería ser más rápido. En JavaScript, sin embargo, el coste dominante es asignar objetos y memoria, algo que ningún decodificador puede evitar. La forma de los datos, el número de campos y la calidad de la implementación influyen, así que la única conclusión fiable sale de medir tus propios payloads en lugar de citar el multiplicador de un proveedor. Si un payload individual es demasiado grande para leerlo en memoria de una vez, córtalo con el enfoque descrito en Parseo y streaming de JSON grande antes de medir la ganancia de codificación.

4. int64 y campos binarios: la verdadera razón para cambiar

El tamaño a menudo no es la razón para cambiar de formato. La expresividad de tipos sí.

4.1 Enteros más allá de 2^53

Los números JSON acaban en un double en JavaScript, así que 9007199254740993 se convierte en 9007199254740992. Los tres formatos binarios manejan esto de forma distinta:

Formato Enteros de 64 bits 64 bits sin signo Precisión arbitraria
MessagePack ✓ int64 (0xd3), decodificable a BigInt ✓ uint64 (0xcf) ✗ (necesita un tipo de extensión)
CBOR ✓ formas de 64 bits del tipo mayor 0/1 ✓ Mismo espacio de codificación ✓ etiquetas bignum 2/3
BSON ✓ int64 (0x12) ✗ Solo con signo ✗ (Decimal128 es de punto fijo, no un entero arbitrario)

CBOR es el único con una representación estándar para enteros de precisión arbitraria: los valores más allá de 64 bits se envuelven con la etiqueta 2 (no negativo) o la etiqueta 3 (negativo) alrededor de una cadena de bytes. MessagePack y BSON recurren a cadenas o a convenciones de extensión propias.

4.2 Payloads binarios

JSON tiene exactamente una forma de expresar binario: Base64, que infla el payload en aproximadamente un tercio y requiere una copia adicional de decodificación. MessagePack tiene tipos bin (0xc4–0xc6), CBOR tiene cadenas de bytes (tipo mayor 2) y BSON tiene subtipos binarios. Cuando transportas imágenes, hashes, vectores o bloques comprimidos, esta diferencia importa mucho más que ahorrar unos bytes de puntuación.

5. Comparación lado a lado

Dimensión MessagePack CBOR BSON
Especificación Especificación de la comunidad RFC 8949 del IETF Ecosistema MongoDB
Media type application/msgpack (no estándar de IANA) application/cbor (registrado en IANA) Sin media type general
Sistema de tipos Seis tipos JSON más bin y ext Seis tipos JSON más bin, etiquetas y valores simples Más amplio: ObjectId, Decimal128, fechas, regex, timestamps
Mecanismo de extensión Tipos de extensión (por ejemplo timestamp -1) Etiquetas (fechas, bignums, CBOR embebido) Códigos de tipo fijos, extensiones por convención del ecosistema
Codificación determinista Sin requisito estándar Reglas explícitas, utilizables para firmas Ninguna
Autodescriptivo Sí, pero sin schema a nivel de campo Sí, y descriptible con CDDL Sí, con nombres de campo repetidos por documento
Sobrecarga en documentos pequeños Baja Baja Alta (prefijo de longitud, nombres de campo, terminador)
Ecosistema Cachés, logs, algo de RPC COSE, WebAuthn, IoT Solo MongoDB

6. Soporte en navegador y Node

Node 24 no incluye ninguno de estos códecs, así que instalas una biblioteca. Opciones habituales:

Runtime MessagePack CBOR BSON
Node.js @msgpack/msgpack, msgpackr cbor-x, borc bson
Navegador @msgpack/msgpack build de navegador de cbor-x, cbor-web bson

Ambas familias funcionan sobre Uint8Array y no requieren Buffer. Vigila las diferencias de versión:

import { encode, decode } from '@msgpack/msgpack';

/**
 * Codifica un objeto en bytes MessagePack y lo decodifica de inmediato para verificarlo.
 * @param payload Objeto plano que se va a codificar
 * @returns El valor decodificado y la longitud en bytes codificada
 */
function roundTrip(payload: Record<string, unknown>): { decoded: unknown; byteLength: number } {
  const bytes = encode(payload);
  return { decoded: decode(bytes), byteLength: bytes.byteLength };
}

La mayoría de las bibliotecas decodifican los enteros grandes a number de forma predeterminada y pierden precisión fuera del rango seguro. Si los valores exactos importan, habilita explícitamente la opción BigInt (useBigInt64 en @msgpack/msgpack, un interruptor equivalente en cbor-x); de lo contrario simplemente has movido el viejo problema de JSON a un formato nuevo.

7. Capacidad de depuración y compatibilidad de protocolo

7.1 Capacidad de depuración: el mayor coste oculto

La mayor ventaja del JSON de texto no es el tamaño; es que puedes abrirlo en cualquier momento. Después de cambiar a binario:

  • grep, awk y jq dejan de funcionar, y los pipelines de logs necesitan un paso extra de decodificación;
  • Depurar producción requiere el decodificador correcto en la versión correcta, o los nombres de campo que veas serán incorrectos;
  • El tráfico capturado aparece en las herramientas de desarrollo del navegador como un bloque de bytes ilegible;
  • Los diffs de revisión de código muestran una ristra de hexadecimal.

CBOR tiene notación diagnóstica, que representa los bytes de nuevo como texto legible cercano a JSON, por ejemplo un map como {1: 2}; MessagePack también tiene algunos decodificadores de línea de comandos. Pero todos requieren instalación adicional y quedan fuera del camino estándar de operaciones.

La conclusión: siempre que las personas necesiten inspeccionar los datos con frecuencia, el coste oculto de un formato binario supera el ancho de banda que ahorra.

7.2 Compatibilidad de protocolo y extensiones

  • CBOR tiene el mecanismo de etiquetas más completo: etiqueta 0 para una cadena de fecha y hora, etiqueta 1 para un timestamp Unix, etiquetas 2 y 3 para bignums, y etiqueta 24 para CBOR embebido. Combinado con la codificación determinista, lo usan protocolos que necesitan firmas y consistencia entre implementaciones, como COSE, WebAuthn y CWT.
  • MessagePack deja los tipos de extensión a los implementadores. En la práctica el único común es timestamp (tipo de extensión -1). Entre equipos, cada tipo de extensión debe quedar escrito en el documento del protocolo o la otra parte no podrá decodificarlo.
  • BSON tiene códigos de tipo fijos, y ObjectId, Decimal128, MinKey y MaxKey son semántica específica de MongoDB. Tratar BSON como formato general de intercambio trae un montón de tipos sin usar y prefijos de longitud sin usar.

Si un protocolo exige que "los mismos datos deben producir los mismos bytes", solo CBOR ofrece una respuesta estándar; MessagePack y BSON necesitan un acuerdo adicional sobre el orden de campos y los detalles de codificación.

8. Cuándo merece la pena cambiar

Señales que justifican un cambio:

  • Los payloads son grandes, ambos extremos pueden cambiar y los tamaños comprimidos siguen difiriendo de forma significativa;
  • Transportas contenido binario y la inflación de Base64 y el coste de decodificación son medibles;
  • Necesitas enteros de 64 bits o decimales exactos que los doubles de JSON no pueden representar;
  • El enlace es servidor a servidor y las herramientas de diagnóstico se pueden estandarizar.

Señales que argumentan en contra:

  • gzip o brotli ya está en marcha y la ganancia es un porcentaje de un dígito;
  • La API es pública y los terceros solo tienen clientes HTTP de propósito general;
  • Los datos son logs o configuración que las personas leen a mano;
  • El equipo no tiene presupuesto para mantener decodificadores y compatibilidad de versiones.

También funciona un camino intermedio: mantén JSON en el exterior y usa MessagePack para cachés internas. Los valores de caché solo los leen tus propios servicios, así que mejoran tanto el tamaño como el coste de parseo, y limpiar la caché resuelve cualquier problema sin tocar el contrato.

9. Lista de comprobación

  • [ ] Compara recuentos de bytes comprimidos con datos reales, no recuentos sin comprimir;
  • [ ] Decide la política de enteros grandes: opción BigInt, transporte como cadena o bignums de CBOR;
  • [ ] Envía los campos binarios como bin o cadenas de bytes en lugar de envolverlos en Base64;
  • [ ] Escribe los tipos de extensión y las etiquetas en el documento del protocolo y fija las versiones de los decodificadores;
  • [ ] Mantén una ruta de depuración con JSON de texto que se pueda habilitar durante incidentes en producción;
  • [ ] Ejecuta un benchmark y registra números reproducibles en lugar de afirmaciones verbales.

¿Cuál es la diferencia entre MessagePack y CBOR?

Sus codificaciones son muy similares: maps, arrays y cadenas usan todos un prefijo compacto de tipo más longitud. La diferencia principal es la estandarización. CBOR es un RFC del IETF con un media type de IANA, un mecanismo de etiquetas y reglas de codificación determinista; MessagePack es una especificación de la comunidad cuyos tipos de extensión dependen de acuerdos privados. Elige CBOR cuando necesites firmas, consistencia entre implementaciones o protocolos para dispositivos limitados.

¿Puede BSON sustituir a JSON como formato general?

No se recomienda. BSON se diseñó para documentos de base de datos: cada documento lleva una longitud total de 4 bytes, cada campo repite su tipo y su nombre, y los documentos pequeños acaban siendo más grandes que el texto JSON. Además incluye tipos específicos de MongoDB como ObjectId y MinKey. Fuera de MongoDB, la mayor parte de su sistema de tipos queda sin usar mientras la penalización de tamaño se mantiene.

¿Cuánto más pequeño hace mi payload un formato binario?

Depende de la forma de los datos. Cuando los nombres de campo se repiten mucho, el JSON de texto comprimido y los formatos binarios acaban parecidos; cuando los nombres son cortos y los datos están llenos de caracteres estructurales y números, la ventaja binaria es más clara. Mide muestras reales sin comprimir y tras gzip, y luego decide, en lugar de estimar con un multiplicador genérico.

¿Puedo seguir depurando datos binarios con jq?

No. jq solo procesa JSON de texto y fallará de inmediato con bytes de MessagePack o CBOR. Tienes que decodificar con la biblioteca correspondiente a JSON y luego pasarlo a jq; CBOR también puede pasar por una herramienta de notación diagnóstica para convertirse en texto legible. Mantener una ruta de depuración de texto es más barato que instalar herramientas sobre la marcha.