Binární JSON: volba mezi MessagePack, CBOR a BSON
Shrnutí: MessagePack, CBOR i BSON komprimují JSON do bajtů. Srovnejte náklady na bajty, zpracování int64 a binárních dat a získejte jasnou hranici, kdy se přechod vyplatí.

Stručně: textový JSON si ponechte pro externí výměnu a pro data, která lidé potřebují prohlížet, a na interní linky přejděte k MessagePack nebo CBOR jen tehdy, když binární payloady, celá čísla nad 2^53 nebo přesná desetinná čísla činí komprimovanou velikost nebo vyjádřivost typů skutečným problémem; BSON patří do ekosystému MongoDB.
Textový JSON šetří prázdné znaky; binární formáty šetří interpunkci a textovou podobu čísel. Názvy polí se stále objevují jednou na záznam, takže než přejdete, spočítejte skutečnou úsporu.
1. Co binární JSON vlastně šetří
Nejprve si nastavte očekávání. Žádný z těchto formátů není „další syntaxe JSON“. Kódují stejný datový model do bajtů: objekty, pole, řetězce, čísla, booleany a null. Co odstraňují, je konkrétní:
- Strukturální znaky jako uvozovky, dvojtečky, čárky a závorky;
- Desetinnou textovou podobu čísel, takže
32se stane jediným bajtem; - Opakované skenování kvůli hranicím řetězců, nahrazené prefixem s pevnou délkou;
- Base64 kódování binárních payloadů, které lze ukládat přímo jako bajty.
Co odstranit nedokážou, je stejně konkrétní: názvy polí se stále objevují jako řetězce v každém záznamu. MessagePack mapa, CBOR mapa i BSON dokument opakují klíč pro každou položku. Když je tedy váš JSON deset tisíc záznamů se stejným tvarem, rozdíl v komprimované velikosti mezi textem a binárkou je mnohem menší, než intuice naznačuje, protože gzip je nejlepší právě v odstraňování opakovaných názvů polí.
2. Odkud tři formáty pocházejí
| Formát | Specifikace a rok | Původ | Typické použití |
|---|---|---|---|
| MessagePack | spec msgpack.org, od 2008 | Nezávislý návrh zaměřený na minimalismus | Hodnoty cache, IPC, logovací pipeline |
| CBOR | RFC 8949 (STD 94), 2020 | Ovlivněn MessagePack, standardizován IETF | COSE, WebAuthn, CWT, omezená zařízení |
| BSON | bsonspec.org, ekosystém MongoDB | Navržen pro databázové dokumenty | Úložiště a drátový protokol MongoDB |
CBOR je nejvíce standardizovaný: mediální typ application/cbor registrovaný v IANA, pravidla deterministického kódování a CDDL pro popis. MessagePack je nejlehčí, se specifikací, která se vejde na stránku. BSON je nejtěžší: do typového systému zabudovává ObjectId, Decimal128, data a binární podtypy, a proto je skutečně populární jen v ekosystému MongoDB.
3. Stejná data, čtyři kódování
Vezměte {"name":"joe"} jako příklad. Náklady na bajty lze snadno srovnat:
| Kódování | Bajty | Bajtová posloupnost |
|---|---|---|
| Textový 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 | 4bajtová celková délka + typový bajt + name\0 + 4bajtová délka hodnoty + joe\0 + terminátor |
Rozložte devět bajtů MessagePack:
81: vysoký nibble1000znamená mapu, nízký nibble0001znamená jednu dvojici klíč-hodnota;a3: vysoké tři bity101znamenají řetězec s pevnou délkou 3;6e 61 6d 65: ASCII proname;a3: další řetězec délky 3;6a 6f 65:joe.
CBOR a1 je hlavní typ 5 (mapa) s délkou 1 a 64 je hlavní typ 3 (textový řetězec) s délkou 4, takže sémantika je téměř izomorfní s MessagePack. BSON je větší: každý dokument nese 4bajtovou celkovou délku, každé pole opakuje typový bajt a svůj název a každý řetězec opakuje délku plus koncový \0. U malých dokumentů může být BSON snadno větší než textový JSON.
Prefixy si můžete zkontrolovat přímo vykreslením těch bajtů jako hex:
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 Velikost a rychlost parsování: ignorujte marketingová čísla
Tvrzení, že binárka je „10x rychlejší“, je třeba rozdělit na dvě otázky.
Velikost. Nekomprimovaná binárka je menší, protože interpunkce a prázdné znaky zmizely. Reálné pipeline však téměř vždy komprimují: po gzip nebo brotli se opakované názvy polí zkomprimují a binární výhoda dramaticky zmenší. Postupujte podle metody v článku Minifikace JSON versus gzip: nejprve měřte komprimované bajty, poté rozhodněte, zda změna formátu stojí za to.
Rychlost parsování. Binárka přeskakuje lexing (skenování uvozovek, čárek a číslic), takže teoreticky má být rychlejší. V JavaScriptu je však dominantním nákladem alokace objektů a paměti, čemuž se žádný dekodér nevyhne. Tvar dat, počet polí i kvalita implementace hrají roli, takže jediný spolehlivý závěr pochází z benchmarku vlastních payloadů, nikoli z citování násobitele výrobce. Pokud je jediný payload příliš velký na načtení do paměti, nakrájejte ho postupem popsaným v Parsování a streamování velkého JSON, než změříte přínos kódování.
4. Pole int64 a binární data: skutečný důvod k přechodu
Velikost často není důvodem ke změně formátu. Vyjádřivost typů je.
4.1 Celá čísla nad 2^53
Čísla JSON v JavaScriptu přistanou v double, takže 9007199254740993 se stane 9007199254740992. Tři binární formáty to řeší různě:
| Formát | 64bitová celá čísla | Nepodepsaná 64bitová | Libovolná přesnost |
|---|---|---|---|
| MessagePack | ✓ int64 (0xd3), dekódovatelné do BigInt |
✓ uint64 (0xcf) |
✗ (vyžaduje rozšiřující typ) |
| CBOR | ✓ 64bitové formy hlavního typu 0/1 | ✓ Stejný kódovací prostor | ✓ bignum tagy 2/3 |
| BSON | ✓ int64 (0x12) |
✗ Jen se znaménkem | ✗ (Decimal128 je pevná řádová čárka, nikoli libovolné celé číslo) |
CBOR je jediný se standardní reprezentací celých čísel s libovolnou přesností: hodnoty nad 64 bitů se obalují tagem 2 (nezáporné) nebo tagem 3 (záporné) kolem bajtového řetězce. MessagePack a BSON se uchylují k řetězcům nebo vlastním konvencím rozšíření.
4.2 Binární payloady
JSON má přesně jeden způsob, jak vyjádřit binárku: Base64, který payload nafoukne zhruba o třetinu a vyžaduje další dekódovací kopii. MessagePack má typy bin (0xc4–0xc6), CBOR má bajtové řetězce (hlavní typ 2) a BSON má binární podtypy. Když přenášíte obrázky, hashe, vektory nebo komprimované bloky, tento rozdíl záleží mnohem více než úspora několika interpunkčních bajtů.
5. Srovnání vedle sebe
| Dimenze | MessagePack | CBOR | BSON |
|---|---|---|---|
| Specifikace | Komunitní specifikace | IETF RFC 8949 | Ekosystém MongoDB |
| Mediální typ | application/msgpack (není standard IANA) |
application/cbor (registrován v IANA) |
Žádný obecný mediální typ |
| Typový systém | Šest typů JSON plus bin a ext | Šest typů JSON plus bin, tagy a jednoduché hodnoty | Širší: ObjectId, Decimal128, data, regex, časová razítka |
| Mechanismus rozšíření | Rozšiřující typy (například timestamp -1) | Tagy (data, bignumy, vnořený CBOR) | Pevné typové kódy, rozšíření podle ekosystémové konvence |
| Deterministické kódování | Žádný standardní požadavek | Explicitní pravidla, použitelná pro podpisy | Žádné |
| Sebe popisné | Ano, ale bez schématu na úrovni polí | Ano, a popsatelné pomocí CDDL | Ano, s názvy polí opakovanými na dokument |
| Režie malého dokumentu | Nízká | Nízká | Vysoká (délkový prefix, názvy polí, terminátor) |
| Ekosystém | Caches, logy, některé RPC | COSE, WebAuthn, IoT | Jen MongoDB |
6. Podpora v prohlížeči a Node
Node 24 neobsahuje žádný z těchto kodeků, takže nainstalujete knihovnu. Běžné volby:
| Běhové prostředí | MessagePack | CBOR | BSON |
|---|---|---|---|
| Node.js | @msgpack/msgpack, msgpackr |
cbor-x, borc |
bson |
| Prohlížeč | @msgpack/msgpack |
build cbor-x pro prohlížeč, cbor-web |
bson |
Obě rodiny pracují s Uint8Array a nevyžadují Buffer. Sledujte rozdíly verzí:
import { encode, decode } from '@msgpack/msgpack';
/**
* Zakóduje objekt do bajtů MessagePack a ihned ho dekóduje pro ověření.
* @param payload Obyčejný objekt ke kódování
* @returns Dekódovaná hodnota a délka zakódovaných bajtů
*/
function roundTrip(payload: Record<string, unknown>): { decoded: unknown; byteLength: number } {
const bytes = encode(payload);
return { decoded: decode(bytes), byteLength: bytes.byteLength };
}
Většina knihoven dekóduje velká celá čísla ve výchozím nastavení na number a za bezpečným rozsahem ztrácí přesnost. Pokud záleží na přesných hodnotách, zapněte explicitně volbu BigInt (useBigInt64 v @msgpack/msgpack, ekvivalentní přepínač v cbor-x), jinak jste jen přesunuli starý problém JSON do nového formátu.
7. Laditelnost a kompatibilita protokolu
7.1 Laditelnost: největší skrytý náklad
Největší výhodou textového JSON není velikost; je to, že ho můžete kdykoli otevřít. Po přechodu na binárku:
grep,awkijqpřestanou fungovat a logovací pipeline potřebuje další dekódovací krok;- Ladění produkce vyžaduje správný dekodér ve správné verzi, jinak budou názvy polí, které vidíte, špatné;
- Zachycený provoz se v nástrojích pro vývojáře prohlížeče zobrazí jako nečitelný bajtový blok;
- Diffy v revizi kódu ukazují řetězec hexadecimálních čísel.
CBOR má diagnostickou notaci, která vykresluje bajty zpět do čitelného textu blízkého JSON, například mapu jako {1: 2}; MessagePack má také několik dekodérů pro příkazový řádek. Všechny však vyžadují dodatečnou instalaci a stojí mimo standardní operační cestu.
Závěr: kdykoli lidé potřebují data často prohlížet, skrytý náklad binárního formátu převyšuje šířku pásma, kterou ušetří.
7.2 Kompatibilita protokolu a rozšíření
- CBOR má nejkompletnější mechanismus tagů: tag 0 pro řetězec s datem a časem, tag 1 pro Unixové časové razítko, tagy 2 a 3 pro bignumy a tag 24 pro vnořený CBOR. V kombinaci s deterministickým kódováním ho používají protokoly, které potřebují podpisy a konzistenci napříč implementacemi, jako COSE, WebAuthn a CWT.
- MessagePack nechává rozšiřující typy na implementátorech. V praxi je jediný běžný timestamp (rozšiřující typ -1). Napříč týmy musí být každý rozšiřující typ zapsán v dokumentu protokolu, jinak ho protější strana nedokáže dekódovat.
- BSON má pevné typové kódy a
ObjectId,Decimal128,MinKeyaMaxKeyjsou sémantika specifická pro MongoDB. Považovat BSON za obecný výměnný formát přináší hromadu nepoužitých typů a nepoužitých délkových prefixů.
Pokud protokol vyžaduje „stejná data musí produkovat stejné bajty“, standardní odpověď existuje jen u CBOR; MessagePack i BSON potřebují další dohodu o pořadí polí a detailech kódování.
8. Kdy se přechod vyplatí
Signály, které přechod ospravedlňují:
- Payloady jsou velké, oba konce lze změnit a komprimované velikosti se stále smysluplně liší;
- Přenášíte binární obsah a nafouknutí Base64 i náklady na dekódování jsou měřitelné;
- Potřebujete 64bitová celá čísla nebo přesná desetinná čísla, která double v JSON neumí reprezentovat;
- Link je server-server a diagnostické nástroje lze standardizovat.
Signály, které mluví proti:
- gzip nebo brotli už je nasazen a přínos je jednociferné procento;
- API je veřejné a třetí strany mají jen obecné HTTP klienty;
- Data jsou logy nebo konfigurace, které lidé čtou ručně;
- Tým nemá rozpočet na údržbu dekodérů a kompatibility verzí.
Funguje i střední cesta: externě držte JSON a pro interní caches používejte MessagePack. Hodnoty cache čtou jen vaše vlastní služby, takže se zlepší velikost i náklady na parsování a vymazání cache vyřeší jakýkoli problém bez zásahu do smlouvy.
9. Kontrolní seznam
- [ ] Srovnávejte komprimované počty bajtů ze skutečných dat, nikoli nekomprimované počty;
- [ ] Rozhodněte politiku velkých celých čísel: volba BigInt, přenos řetězcem, nebo CBOR bignumy;
- [ ] Binární pole posílejte jako bin nebo bajtové řetězce, místo abyste je obalovali Base64;
- [ ] Rozšiřující typy a tagy zapište do dokumentu protokolu a zafixujte verze dekodérů;
- [ ] Udržujte ladicí cestu s textovým JSON, kterou lze zapnout během produkčních incidentů;
- [ ] Spusťte benchmark a zaznamenejte reprodukovatelná čísla místo slovních tvrzení.
Jaký je rozdíl mezi MessagePack a CBOR?
Jejich kódování jsou velmi podobná: mapy, pole i řetězce používají kompaktní prefix typu a délky. Hlavní rozdíl je standardizace. CBOR je IETF RFC s mediálním typem v IANA, mechanismem tagů a pravidly deterministického kódování; MessagePack je komunitní specifikace, jejíž rozšiřující typy závisí na soukromých dohodách. CBOR zvolte, když potřebujete podpisy, konzistenci napříč implementacemi nebo protokoly pro omezená zařízení.
Může BSON nahradit JSON jako obecný formát?
Nedoporučuje se. BSON byl navržen pro databázové dokumenty: každý dokument nese 4bajtovou celkovou délku, každé pole opakuje svůj typ a název a malé dokumenty nakonec končí větší než textový JSON. Obsahuje také typy specifické pro MongoDB, jako ObjectId a MinKey. Mimo MongoDB je většina jeho typového systému nevyužitá, zatímco velikostní penalizace zůstává.
O kolik menší binární formát udělá můj payload?
Záleží na tvaru dat. Když se názvy polí silně opakují, komprimovaný textový JSON a binární formáty skončí blízko sebe; když jsou názvy krátké a data plná strukturálních znaků a čísel, binární výhoda je jasnější. Změřte skutečné vzorky nekomprimované i po gzip, a poté se rozhodněte, místo abyste odhadovali obecným násobitelem.
Můžu binární data stále ladit pomocí jq?
Ne. jq zpracovává jen textový JSON a na bajtech MessagePack nebo CBOR okamžitě selže. Nejdříve musíte dekódovat odpovídající knihovnou do JSON a poté ho předat jq; CBOR může také projít nástrojem s diagnostickou notací a stát se čitelným textem. Udržovat ladicí cestu s textem je levnější než instalovat nástroje na vyžádání.