Binary JSON: MessagePack, CBOR और BSON में चयन
मुख्य बात: MessagePack, CBOR और BSON तीनों JSON को bytes में compress करते हैं। Byte लागत, int64 और binary handling की तुलना करें, और तय करें कि बदलाव कब फ़ायदेमंद है।

सार: बाहरी आदान-प्रदान और जिन डेटा को लोगों को जाँचना है उनके लिए text JSON रखें, और आंतरिक links पर MessagePack या CBOR तभी अपनाएँ जब binary payloads, 2^53 से बड़े integers या सटीक decimals compressed आकार या type expressiveness को असली समस्या बना दें; BSON MongoDB पारिस्थितिकी तंत्र का है।
Text JSON whitespace बचाता है; binary formats punctuation और संख्याओं का textual रूप बचाते हैं। Field नाम अब भी प्रति record एक बार आते हैं, इसलिए बदलने से पहले असली बचत निकालें।
1. Binary JSON असल में क्या बचाता है
पहले अपेक्षाएँ तय करें। इनमें से कोई format "दूसरा JSON syntax" नहीं है। वे वही data model bytes में encode करते हैं: objects, arrays, strings, numbers, booleans और null। वे जो हटाते हैं वह ठोस है:
- Quotes, colons, commas और braces जैसे structural characters;
- संख्याओं का decimal text रूप, इसलिए
32एक byte बन जाता है; - String सीमाओं के लिए दोबारा scanning, जिसकी जगह निश्चित-लंबाई prefix आता है;
- Binary payloads के लिए Base64 encoding, जिन्हें सीधे bytes के रूप में रखा जा सकता है।
वे जो नहीं हटा सकते वह भी उतना ही ठोस है: field नाम अब भी हर record में strings के रूप में आते हैं। MessagePack map, CBOR map और BSON document सभी हर entry के लिए key दोहराते हैं। इसलिए जब आपका JSON एक ही आकार के दस हज़ार records का है, तो text और binary के बीच compressed आकार का अंतर अंदाज़े से कहीं कम होता है, क्योंकि gzip बार-बार आने वाले field नाम हटाने में सबसे अच्छा है।
2. तीनों formats कहाँ से आते हैं
| Format | Specification और वर्ष | मूल | सामान्य उपयोग |
|---|---|---|---|
| MessagePack | msgpack.org spec, 2008 से | न्यूनतमवाद पर केंद्रित स्वतंत्र डिज़ाइन | Cache मान, IPC, log pipelines |
| CBOR | RFC 8949 (STD 94), 2020 | MessagePack से प्रभावित, IETF द्वारा मानकीकृत | COSE, WebAuthn, CWT, सीमित उपकरण |
| BSON | bsonspec.org, MongoDB पारिस्थितिकी तंत्र | Database documents के लिए डिज़ाइन | MongoDB storage और wire protocol |
CBOR सबसे मानकीकृत है: IANA-पंजीकृत application/cbor media type, deterministic encoding नियम, और वर्णन के लिए CDDL। MessagePack सबसे हल्का है, जिसका specification एक पृष्ठ में आ जाता है। BSON सबसे भारी है: यह ObjectId, Decimal128, dates और binary subtypes को अपने type system में शामिल करता है, इसीलिए यह वास्तव में केवल MongoDB पारिस्थितिकी तंत्र के भीतर लोकप्रिय है।
3. वही डेटा, चार encodings
{"name":"joe"} को उदाहरण लें। Byte लागत की तुलना आसान है:
| Encoding | Bytes | Byte क्रम |
|---|---|---|
| JSON text | 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 | 4-byte total length + type byte + name\0 + 4-byte value length + joe\0 + terminator |
MessagePack के नौ bytes को अलग-अलग देखें:
81: high nibble1000का अर्थ map, low nibble0001का अर्थ एक key-value pair;a3: high तीन bits101का अर्थ लंबाई 3 की fixed-length string;6e 61 6d 65:nameके लिए ASCII;a3: लंबाई 3 की एक और string;6a 6f 65:joe.
CBOR का a1 major type 5 (map) है लंबाई 1 के साथ, और 64 major type 3 (text string) है लंबाई 4 के साथ, इसलिए semantics लगभग MessagePack के समरूप हैं। BSON बड़ा है: हर document 4-byte total length रखता है, हर field type byte और अपना नाम दोहराता है, और हर string लंबाई के साथ अंत में \0 दोहराती है। छोटे documents पर, BSON आसानी से JSON text से बड़ा हो सकता है।
आप उन bytes को hex में render करके prefixes सीधे जाँच सकते हैं:
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 आकार और parse गति: marketing संख्याओं को नज़रअंदाज़ करें
Binary "10x तेज़" होने के दावों को दो प्रश्नों में बाँटना चाहिए।
आकार। Uncompressed, binary छोटा है क्योंकि punctuation और whitespace चले गए हैं। पर असली pipelines लगभग हमेशा compress करती हैं: gzip या brotli के बाद, बार-बार आने वाले field नाम compress हो जाते हैं, और binary का लाभ नाटकीय रूप से सिकुड़ जाता है। JSON minification बनाम gzip की विधि अपनाएँ: पहले compressed bytes मापें, फिर तय करें कि format बदलना फ़ायदेमंद है या नहीं।
Parse गति। Binary lexing (quotes, commas और number characters scan करना) छोड़ देता है, इसलिए सिद्धांत रूप में उसे तेज़ होना चाहिए। पर JavaScript में प्रमुख लागत objects और memory allocate करना है, जिसे कोई decoder टाल नहीं सकता। Data shape, field count और implementation गुणवत्ता सब मायने रखते हैं, इसलिए एकमात्र भरोसेमंद निष्कर्ष अपने payloads पर benchmark चलाने से आता है, vendor के multiplier उद्धृत करने से नहीं। अगर एक payload एक बार में memory में पढ़ने के लिए बहुत बड़ा है, तो encoding लाभ मापने से पहले उसे बड़ी JSON का parsing और streaming में बताए तरीके से slice करें।
4. int64 और binary fields: बदलाव का असली कारण
आकार अक्सर format बदलने का कारण नहीं होता। Type expressiveness होती है।
4.1 2^53 से बड़े integers
JavaScript में JSON संख्याएँ double में बैठती हैं, इसलिए 9007199254740993 9007199254740992 बन जाता है। तीनों binary formats इसे अलग तरह संभालते हैं:
| Format | 64-bit integers | Unsigned 64-bit | Arbitrary precision |
|---|---|---|---|
| MessagePack | ✓ int64 (0xd3), BigInt में decodable |
✓ uint64 (0xcf) |
✗ (extension type चाहिए) |
| CBOR | ✓ major type 0/1 के 64-bit रूप | ✓ वही encoding space | ✓ bignum tags 2/3 |
| BSON | ✓ int64 (0x12) |
✗ केवल signed | ✗ (Decimal128 fixed-point है, arbitrary integer नहीं) |
CBOR ही एकमात्र है जिसके पास arbitrary-precision integers का मानक प्रतिनिधित्व है: 64 bits से बड़े मान एक byte string के चारों ओर tag 2 (non-negative) या tag 3 (negative) में लिपटे जाते हैं। MessagePack और BSON strings या अपने extension conventions पर लौटते हैं।
4.2 Binary payloads
JSON के पास binary व्यक्त करने का ठीक एक तरीका है: Base64, जो payload को लगभग एक-तिहाई बढ़ा देता है और एक अतिरिक्त decode copy माँगता है। MessagePack के पास bin types (0xc4–0xc6) हैं, CBOR के पास byte strings (major type 2), और BSON के पास binary subtypes। जब आप images, hashes, vectors या compressed blocks transport करते हैं, तो यह अंतर कुछ punctuation bytes बचाने से कहीं अधिक मायने रखता है।
5. साथ-साथ तुलना
| आयाम | MessagePack | CBOR | BSON |
|---|---|---|---|
| Specification | Community spec | IETF RFC 8949 | MongoDB पारिस्थितिकी तंत्र |
| Media type | application/msgpack (IANA-मानक नहीं) |
application/cbor (IANA-पंजीकृत) |
कोई सामान्य media type नहीं |
| Type system | छह JSON प्रकार + bin और ext | छह JSON प्रकार + bin, tags और simple values | व्यापक: ObjectId, Decimal128, dates, regex, timestamps |
| Extension mechanism | Extension types (जैसे timestamp -1) | Tags (dates, bignums, embedded CBOR) | निश्चित type codes, ecosystem convention से extensions |
| Deterministic encoding | कोई मानक आवश्यकता नहीं | स्पष्ट नियम, signatures के लिए उपयोगी | कोई नहीं |
| Self-describing | हाँ, पर field-स्तर schema नहीं | हाँ, और CDDL से वर्णन योग्य | हाँ, प्रति document field नाम दोहराए जाते हैं |
| छोटे-document overhead | कम | कम | अधिक (length prefix, field नाम, terminator) |
| पारिस्थितिकी तंत्र | Caches, logs, कुछ RPC | COSE, WebAuthn, IoT | केवल MongoDB |
6. Browser और Node समर्थन
Node 24 इनमें से कोई codec नहीं देता, इसलिए आप एक लाइब्रेरी install करते हैं। सामान्य विकल्प:
| Runtime | MessagePack | CBOR | BSON |
|---|---|---|---|
| Node.js | @msgpack/msgpack, msgpackr |
cbor-x, borc |
bson |
| Browser | @msgpack/msgpack |
cbor-x browser build, cbor-web |
bson |
दोनों परिवार Uint8Array पर काम करते हैं और Buffer नहीं माँगते। संस्करण अंतर देखें:
import { encode, decode } from '@msgpack/msgpack';
/**
* किसी object को MessagePack bytes में encode करता है और सत्यापन के लिए तुरंत decode करता है।
* @param payload encode करने योग्य सादा object
* @returns Decoded मान और encoded byte लंबाई
*/
function roundTrip(payload: Record<string, unknown>): { decoded: unknown; byteLength: number } {
const bytes = encode(payload);
return { decoded: decode(bytes), byteLength: bytes.byteLength };
}
ज़्यादातर लाइब्रेरी डिफ़ॉल्ट रूप से बड़े integers को number में decode करती हैं और safe range से आगे सटीकता खो देती हैं। अगर सटीक मान मायने रखते हैं, तो BigInt विकल्प स्पष्ट रूप से सक्षम करें (@msgpack/msgpack में useBigInt64, cbor-x में समकक्ष switch), वरना आपने JSON की पुरानी समस्या को बस नए format में ला दिया है।
7. Debuggability और protocol compatibility
7.1 Debuggability: सबसे बड़ी छिपी लागत
Text JSON का सबसे बड़ा लाभ आकार नहीं; यह है कि आप उसे कभी भी खोल सकते हैं। Binary पर जाने के बाद:
grep,awkऔरjqसब काम करना बंद कर देते हैं, और log pipelines को एक अतिरिक्त decode चरण चाहिए;- Production debugging के लिए सही संस्करण में सही decoder चाहिए, वरना आपके देखे field नाम गलत होंगे;
- Captured traffic browser developer tools में एक अपठनीय byte blob बनकर दिखता है;
- Code review diffs hexadecimal की लड़ी दिखाते हैं।
CBOR का diagnostic notation है, जो bytes को JSON के करीब पठनीय text में लौटाता है, उदाहरण के लिए map को {1: 2} के रूप में; MessagePack के भी कुछ command-line decoders हैं। पर सभी को अतिरिक्त installation चाहिए और वे मानक operations path से बाहर बैठते हैं।
निष्कर्ष: जब भी लोगों को डेटा बार-बार जाँचना हो, binary format की छिपी लागत उस बैंडविड्थ से अधिक होती है जो वह बचाता है।
7.2 Protocol compatibility और extensions
- CBOR के पास सबसे पूर्ण tag mechanism है: date-time string के लिए tag 0, Unix timestamp के लिए tag 1, bignums के लिए tags 2 और 3, और embedded CBOR के लिए tag 24। Deterministic encoding के साथ मिलकर, इसका उपयोग ऐसे protocols करते हैं जिन्हें signatures और cross-implementation consistency चाहिए, जैसे COSE, WebAuthn और CWT।
- MessagePack extension types implementers पर छोड़ता है। व्यवहार में एकमात्र आम timestamp (extension type -1) है। Teams के बीच, हर extension type प्रोटोकॉल दस्तावेज़ में लिखा जाना चाहिए, वरना दूसरा पक्ष decode नहीं कर सकेगा।
- BSON के पास निश्चित type codes हैं, और
ObjectId,Decimal128,MinKeyवMaxKeyMongoDB-विशिष्ट semantics हैं। BSON को सामान्य interchange format मानने से बेकार types और बेकार length prefixes का ढेर आ जाता है।
अगर किसी protocol को "वही डेटा हमेशा वही bytes दे" चाहिए, तो केवल CBOR मानक उत्तर देता है; MessagePack और BSON दोनों को field order और encoding विवरण पर अतिरिक्त सहमति चाहिए।
8. कब बदलना फ़ायदेमंद है
बदलाव को जायज़ ठहराने वाले संकेत:
- Payloads बड़े हैं, दोनों सिरे बदल सकते हैं, और compressed आकार में फिर भी अर्थपूर्ण अंतर है;
- आप binary सामग्री transport करते हैं और Base64 का फुलाव व decode लागत मापी जा सकती है;
- आपको 64-bit integers या सटीक decimals चाहिए जिन्हें JSON doubles व्यक्त नहीं कर सकते;
- Link server-to-server है और diagnostic tooling मानकीकृत की जा सकती है।
इसके विरुद्ध तर्क देने वाले संकेत:
- gzip या brotli पहले से मौजूद है और लाभ एक-अंकीय प्रतिशत है;
- API public है और तीसरे पक्ष के पास केवल सामान्य-प्रयोजन HTTP clients हैं;
- डेटा logs या configuration है जिसे लोग हाथ से पढ़ते हैं;
- टीम के पास decoders और संस्करण compatibility बनाए रखने का budget नहीं है।
बीच का रास्ता भी काम करता है: बाहर JSON रखें और आंतरिक caches के लिए MessagePack इस्तेमाल करें। Cache मान केवल आपकी अपनी services पढ़ती हैं, इसलिए आकार और parse लागत दोनों सुधरते हैं, और cache साफ़ करने से अनुबंध छुए बिना कोई भी समस्या हल हो जाती है।
9. जाँच सूची
- [ ] असली डेटा से compressed byte counts की तुलना करें, uncompressed counts से नहीं;
- [ ] Big-integer नीति तय करें: BigInt विकल्प, string transport, या CBOR bignums;
- [ ] Binary fields को Base64 में लपेटने के बजाय bin या byte strings के रूप में भेजें;
- [ ] Extension types और tags प्रोटोकॉल दस्तावेज़ में लिखें और decoder संस्करण pin करें;
- [ ] एक text-JSON debug path रखें जो production घटनाओं के दौरान सक्षम किया जा सके;
- [ ] Benchmark चलाएँ और पुनरुत्पाद्य संख्याएँ दर्ज करें, मौखिक दावे नहीं।
MessagePack और CBOR में क्या अंतर है?
उनके encodings बहुत समान हैं: maps, arrays और strings सब compact type-plus-length prefix इस्तेमाल करते हैं। मुख्य अंतर मानकीकरण है। CBOR एक IETF RFC है जिसके पास IANA media type, tag mechanism और deterministic encoding नियम हैं; MessagePack एक समुदाय specification है जिसके extension types निजी सहमतियों पर निर्भर हैं। जब आपको signatures, cross-implementation consistency या सीमित-उपकरण protocols चाहिए, तो CBOR चुनें।
क्या BSON सामान्य format के रूप में JSON की जगह ले सकता है?
सुझाया नहीं जाता। BSON database documents के लिए डिज़ाइन हुआ: हर document 4-byte total length रखता है, हर field अपना type और नाम दोहराता है, और छोटे documents JSON text से बड़े हो जाते हैं। इसमें ObjectId और MinKey जैसे MongoDB-विशिष्ट types भी हैं। MongoDB के बाहर, इसका ज़्यादातर type system अनुपयोगी है जबकि आकार की सज़ा बनी रहती है।
Binary format मेरे payload को कितना छोटा करता है?
यह data shape पर निर्भर है। जब field नाम बहुत दोहराए जाते हैं, तो compressed text JSON और binary formats करीब आ जाते हैं; जब नाम छोटे हों और डेटा structural characters व संख्याओं से भरा हो, तो binary का लाभ स्पष्ट है। असली samples को uncompressed और gzip के बाद दोनों तरह मापें, फिर तय करें, सामान्य multiplier से अनुमान न लगाएँ।
क्या मैं अब भी jq से binary डेटा debug कर सकता हूँ?
नहीं। jq केवल text JSON process करता है और MessagePack या CBOR bytes पर तुरंत fail हो जाएगा। आपको पहले मिलती-जुलती लाइब्रेरी से JSON में decode करना होगा और फिर jq को देना होगा; CBOR diagnostic-notation उपकरण से भी पठनीय text बन सकता है। Text debug path रखना माँग पर tooling install करने से सस्ता है।