JSON Toolkit

JSON Binari: Memilih Antara MessagePack, CBOR dan BSON

Inti pati: MessagePack, CBOR dan BSON semuanya memampatkan JSON menjadi bait. Bandingkan kos bait, pengendalian int64 dan binari, dan dapatkan garis yang jelas untuk bila pertukaran itu berbaloi.

Pertengahan~10 min bacaanDiterbitkan 2026-10-31Dikemas kini 2026-10-31
Kulit perbandingan format JSON binari MessagePack, CBOR dan BSON

Kesimpulan utama: kekalkan JSON teks untuk pertukaran luar dan untuk data yang perlu diperiksa orang, dan tukar kepada MessagePack atau CBOR pada pautan dalaman hanya apabila muatan binari, integer melebihi 2^53, atau perpuluhan tepat menjadikan saiz termampat atau kuasa ekspresif jenis masalah sebenar; BSON tergolong dalam ekosistem MongoDB.

JSON teks menjimatkan ruang putih; format binari menjimatkan tanda baca dan bentuk tekstual nombor. Nama medan masih muncul sekali per rekod, jadi kira penjimatan sebenar sebelum bertukar.

1. Apa yang sebenarnya dijimatkan oleh JSON binari

Tetapkan jangkaan dahulu. Tiada satu pun format ini "sintaks JSON yang lain". Mereka mengekodkan model data yang sama dalam bait: objek, tatasusunan, rentetan, nombor, boolean dan null. Apa yang mereka buang adalah konkrit:

  • Aksara struktur seperti tanda petik, titik bertindih, koma dan kurungan;
  • Bentuk teks perpuluhan nombor, jadi 32 menjadi satu bait;
  • Pengimbasan semula untuk sempadan rentetan, digantikan dengan awalan panjang tetap;
  • Pengekodan Base64 untuk muatan binari, yang boleh disimpan sebagai bait secara terus.

Apa yang mereka tidak boleh buang juga sama konkrit: nama medan masih muncul sebagai rentetan dalam setiap rekod. Peta MessagePack, peta CBOR dan dokumen BSON semuanya mengulang kunci untuk setiap entri. Jadi apabila JSON anda ialah sepuluh ribu rekod dengan bentuk yang sama, jurang saiz termampat antara teks dan binari jauh lebih kecil daripada yang dijangka gerak hati, kerana gzip paling baik menghapuskan nama medan berulang.

2. Dari mana datangnya tiga format ini

Format Spesifikasi dan tahun Asal Kegunaan tipikal
MessagePack spesifikasi msgpack.org, sejak 2008 Reka bentuk bebas yang memberi tumpuan kepada minimalisme Nilai cache, IPC, saluran log
CBOR RFC 8949 (STD 94), 2020 Dipengaruhi oleh MessagePack, distandardkan oleh IETF COSE, WebAuthn, CWT, peranti terhad
BSON bsonspec.org, ekosistem MongoDB Direka untuk dokumen pangkalan data Storan dan protokol wayar MongoDB

CBOR ialah yang paling distandardkan: jenis media application/cbor berdaftar IANA, peraturan pengekodan deterministik, dan CDDL untuk penerangan. MessagePack ialah yang paling ringan, dengan spesifikasi yang muat pada satu halaman. BSON ialah yang paling berat: ia membakar ObjectId, Decimal128, tarikh dan subjenis binari ke dalam sistem jenisnya, sebab itulah ia hanya benar-benar popular dalam ekosistem MongoDB.

3. Data yang sama, empat pengekodan

Ambil {"name":"joe"} sebagai contoh. Kos bait mudah dibandingkan:

Pengekodan Bait Jujukan bait
Teks 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 Panjang keseluruhan 4 bait + bait jenis + name\0 + panjang nilai 4 bait + joe\0 + penamat

Pecahkan sembilan bait MessagePack:

  • 81: nibble tinggi 1000 bermaksud peta, nibble rendah 0001 bermaksud satu pasangan nilai kunci;
  • a3: tiga bit tinggi 101 bermaksud rentetan panjang tetap dengan panjang 3;
  • 6e 61 6d 65: ASCII untuk name;
  • a3: satu lagi rentetan dengan panjang 3;
  • 6a 6f 65: joe.

a1 CBOR ialah jenis utama 5 (peta) dengan panjang 1, dan 64 ialah jenis utama 3 (rentetan teks) dengan panjang 4, jadi semantiknya hampir isomorfik dengan MessagePack. BSON lebih besar: setiap dokumen membawa panjang keseluruhan 4 bait, setiap medan mengulang bait jenis dan namanya, dan setiap rentetan mengulang panjang ditambah \0 di hujung. Pada dokumen kecil, BSON mudah lebih besar daripada teks JSON.

Anda boleh menyemak awalan secara terus dengan memaparkan bait itu sebagai heks:

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 Saiz dan kelajuan penghuraian: abaikan nombor pemasaran

Dakwaan bahawa binari "10 kali lebih pantas" patut dipecahkan kepada dua soalan.

Saiz. Tanpa pemampatan, binari lebih kecil kerana tanda baca dan ruang putih tiada. Tetapi saluran sebenar hampir selalu memampatkan: selepas gzip atau brotli, nama medan berulang dimampatkan hilang, dan kelebihan binari menyusut secara dramatik. Ikuti kaedah dalam Pemampatan JSON berbanding gzip: ukur bait termampat dahulu, kemudian putuskan sama ada perubahan format berbaloi.

Kelajuan penghuraian. Binari melangkau leksing (mengimbas tanda petik, koma dan aksara nombor), jadi ia sepatutnya lebih pantas secara teori. Dalam JavaScript, walau bagaimanapun, kos dominan ialah memperuntukkan objek dan memori, yang tiada penyahkod boleh elakkan. Bentuk data, bilangan medan dan kualiti pelaksanaan semuanya penting, jadi satu-satunya kesimpulan yang boleh dipercayai datang daripada penanda aras muatan anda sendiri dan bukannya memetik pengganda vendor. Jika satu muatan terlalu besar untuk dibaca ke dalam memori sekali gus, hirisnya dengan pendekatan yang diterangkan dalam penghuraian dan penstriman JSON besar sebelum mengukur keuntungan pengekodan.

4. Medan int64 dan binari: sebab sebenar untuk bertukar

Saiz selalunya bukan sebab untuk menukar format. Kuasa ekspresif jenis adalah.

4.1 Integer melebihi 2^53

Nombor JSON mendarat dalam double dalam JavaScript, jadi 9007199254740993 menjadi 9007199254740992. Tiga format binari mengendalikan ini secara berbeza:

Format Integer 64-bit 64-bit tidak bertanda Ketepatan sewenang-wenangnya
MessagePack ✓ int64 (0xd3), boleh dinyahkod kepada BigInt ✓ uint64 (0xcf) ✗ (memerlukan jenis sambungan)
CBOR ✓ bentuk 64-bit jenis utama 0/1 ✓ Ruang pengekodan yang sama ✓ tag bignum 2/3
BSON ✓ int64 (0x12) ✗ Bertanda sahaja ✗ (Decimal128 ialah titik tetap, bukan integer sewenang-wenangnya)

CBOR ialah satu-satunya dengan perwakilan standard untuk integer ketepatan sewenang-wenangnya: nilai melebihi 64 bit dibalut dalam tag 2 (bukan negatif) atau tag 3 (negatif) di sekeliling rentetan bait. MessagePack dan BSON jatuh kembali kepada rentetan atau konvensyen sambungan khas.

4.2 Muatan binari

JSON mempunyai tepat satu cara untuk menyatakan binari: Base64, yang mengembungkan muatan sekitar satu pertiga dan memerlukan salinan nyahkod tambahan. MessagePack mempunyai jenis bin (0xc4–0xc6), CBOR mempunyai rentetan bait (jenis utama 2), dan BSON mempunyai subjenis binari. Apabila anda mengangkut imej, cincang, vektor atau blok termampat, perbezaan ini jauh lebih penting daripada menjimatkan beberapa bait tanda baca.

5. Perbandingan sebelah-menyebelah

Dimensi MessagePack CBOR BSON
Spesifikasi Spesifikasi komuniti RFC 8949 IETF Ekosistem MongoDB
Jenis media application/msgpack (bukan standard IANA) application/cbor (berdaftar IANA) Tiada jenis media umum
Sistem jenis Enam jenis JSON ditambah bin dan ext Enam jenis JSON ditambah bin, tag dan nilai mudah Lebih luas: ObjectId, Decimal128, tarikh, regex, cap masa
Mekanisme sambungan Jenis sambungan (contohnya cap masa -1) Tag (tarikh, bignum, CBOR terbenam) Kod jenis tetap, sambungan mengikut konvensyen ekosistem
Pengekodan deterministik Tiada keperluan standard Peraturan eksplisit, boleh digunakan untuk tandatangan Tiada
Penerangan kendiri Ya, tetapi tiada skema peringkat medan Ya, dan boleh diterangkan dengan CDDL Ya, dengan nama medan diulang per dokumen
Overhed dokumen kecil Rendah Rendah Tinggi (awalan panjang, nama medan, penamat)
Ekosistem Cache, log, sesetengah RPC COSE, WebAuthn, IoT MongoDB sahaja

6. Sokongan pelayar dan Node

Node 24 tidak menyertakan mana-mana kodek ini, jadi anda memasang pustaka. Pilihan biasa:

Masa jalan MessagePack CBOR BSON
Node.js @msgpack/msgpack, msgpackr cbor-x, borc bson
Pelayar @msgpack/msgpack Binaan pelayar cbor-x, cbor-web bson

Kedua-dua keluarga berfungsi pada Uint8Array dan tidak memerlukan Buffer. Perhatikan perbezaan versi:

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

/**
 * Mengekod objek kepada bait MessagePack dan menyahkodnya semula untuk pengesahan.
 * @param payload Objek biasa untuk dikodkan
 * @returns Nilai yang dinyahkod dan panjang bait yang dikodkan
 */
function roundTrip(payload: Record<string, unknown>): { decoded: unknown; byteLength: number } {
  const bytes = encode(payload);
  return { decoded: decode(bytes), byteLength: bytes.byteLength };
}

Kebanyakan pustaka menyahkod integer besar kepada number secara lalai dan kehilangan ketepatan di luar julat selamat. Jika nilai tepat penting, aktifkan pilihan BigInt secara eksplisit (useBigInt64 dalam @msgpack/msgpack, suis setara dalam cbor-x), jika tidak anda hanya memindahkan masalah lama JSON ke format baharu.

7. Kebolehdebugan dan keserasian protokol

7.1 Kebolehdebugan: kos tersembunyi terbesar

Kelebihan terbesar JSON teks bukanlah saiz; ia adalah anda boleh membukanya pada bila-bila masa. Selepas bertukar kepada binari:

  • grep, awk dan jq semuanya berhenti berfungsi, dan saluran log memerlukan langkah nyahkod tambahan;
  • Menyahbug produksi memerlukan penyahkod yang betul pada versi yang betul, atau nama medan yang anda lihat akan salah;
  • Trafik yang ditangkap muncul dalam alat pembangun pelayar sebagai gumpalan bait tidak boleh dibaca;
  • Diff semakan kod menunjukkan rentetan heksadesimal.

CBOR mempunyai notasi diagnostik, yang memaparkan bait semula kepada teks boleh dibaca yang dekat dengan JSON, contohnya peta sebagai {1: 2}; MessagePack juga mempunyai beberapa penyahkod baris arahan. Tetapi semuanya memerlukan pemasaian tambahan dan berada di luar laluan operasi standard.

Kesimpulan: setiap kali orang perlu memeriksa data dengan kerap, kos tersembunyi format binari melebihi lebar jalur yang dijimatkannya.

7.2 Keserasian protokol dan sambungan

  • CBOR mempunyai mekanisme tag paling lengkap: tag 0 untuk rentetan tarikh-masa, tag 1 untuk cap masa Unix, tag 2 dan 3 untuk bignum, dan tag 24 untuk CBOR terbenam. Digabungkan dengan pengekodan deterministik, ia digunakan oleh protokol yang memerlukan tandatangan dan konsistensi merentas pelaksanaan, seperti COSE, WebAuthn dan CWT.
  • MessagePack menyerahkan jenis sambungan kepada pelaksana. Dalam amalan, satu-satunya yang biasa ialah cap masa (jenis sambungan -1). Merentas pasukan, setiap jenis sambungan mesti ditulis dalam dokumen protokol atau pihak lain tidak boleh menyahkodnya.
  • BSON mempunyai kod jenis tetap, dan ObjectId, Decimal128, MinKey dan MaxKey ialah semantik khusus MongoDB. Menganggap BSON sebagai format pertukaran umum membawa timbunan jenis tidak terpakai dan awalan panjang tidak terpakai.

Jika protokol memerlukan "data yang sama mesti menghasilkan bait yang sama", hanya CBOR memberikan jawapan standard; MessagePack dan BSON kedua-duanya memerlukan persetujuan tambahan tentang susunan medan dan butiran pengekodan.

8. Bila ia berbaloi bertukar

Isyarat yang mewajarkan pertukaran:

  • Muatan besar, kedua-dua hujung boleh berubah, dan saiz termampat masih berbeza secara bermakna;
  • Anda mengangkut kandungan binari dan pengembungan Base64 serta kos nyahkod boleh diukur;
  • Anda memerlukan integer 64-bit atau perpuluhan tepat yang tidak boleh diwakili oleh double JSON;
  • Pautan adalah pelayan-ke-pelayan dan perkakasan diagnostik boleh distandardkan.

Isyarat yang menyokong untuk tidak bertukar:

  • gzip atau brotli sudah ada dan keuntungan hanya peratusan satu digit;
  • API adalah awam dan pihak ketiga hanya mempunyai pelanggan HTTP serba guna;
  • Data ialah log atau konfigurasi yang dibaca orang dengan tangan;
  • Pasukan tiada bajet untuk menyelenggara penyahkod dan keserasian versi.

Laluan pertengahan juga berfungsi: kekalkan JSON secara luaran dan gunakan MessagePack untuk cache dalaman. Nilai cache hanya dibaca oleh perkhidmatan anda sendiri, jadi saiz dan kos penghuraian kedua-duanya bertambah baik, dan mengosongkan cache menyelesaikan apa-apa masalah tanpa menyentuh kontrak.

9. Senarai semak

  • [ ] Bandingkan kiraan bait termampat daripada data sebenar, bukan kiraan tidak termampat;
  • [ ] Putuskan dasar integer besar: pilihan BigInt, pengangkutan rentetan, atau bignum CBOR;
  • [ ] Hantar medan binari sebagai bin atau rentetan bait dan bukannya membalutnya dalam Base64;
  • [ ] Tulis jenis sambungan dan tag dalam dokumen protokol dan pasak versi penyahkod;
  • [ ] Kekalkan laluan debug JSON teks yang boleh diaktifkan semasa insiden produksi;
  • [ ] Jalankan penanda aras dan rekod nombor yang boleh diterbitkan semula dan bukannya dakwaan lisan.

Apakah perbezaan antara MessagePack dan CBOR?

Pengekodan mereka sangat serupa: peta, tatasusunan dan rentetan semuanya menggunakan awalan jenis-ditambah-panjang yang mampat. Perbezaan utama ialah penstandardan. CBOR ialah RFC IETF dengan jenis media IANA, mekanisme tag dan peraturan pengekodan deterministik; MessagePack ialah spesifikasi komuniti yang jenis sambungannya bergantung pada persetujuan persendirian. Pilih CBOR apabila anda memerlukan tandatangan, konsistensi merentas pelaksanaan atau protokol peranti terhad.

Bolehkah BSON menggantikan JSON sebagai format umum?

Tidak disyorkan. BSON direka untuk dokumen pangkalan data: setiap dokumen membawa panjang keseluruhan 4 bait, setiap medan mengulang jenis dan namanya, dan dokumen kecil menjadi lebih besar daripada teks JSON. Ia juga merangkumi jenis khusus MongoDB seperti ObjectId dan MinKey. Di luar MongoDB, kebanyakan sistem jenisnya tidak digunakan manakala penalti saiz kekal.

Berapa kecil format binari menjadikan muatan saya?

Ia bergantung pada bentuk data. Apabila nama medan berulang dengan banyak, JSON teks termampat dan format binari berakhir hampir sama; apabila nama pendek dan data penuh dengan aksara struktur serta nombor, kelebihan binari lebih jelas. Ukur sampel sebenar kedua-duanya tanpa pemampatan dan selepas gzip, kemudian putuskan, dan bukannya menganggar dengan pengganda generik.

Bolehkah saya masih menyahbug data binari dengan jq?

Tidak. jq hanya memproses JSON teks dan akan gagal serta-merta pada bait MessagePack atau CBOR. Anda mesti menyahkod dengan pustaka yang sepadan kepada JSON dahulu dan kemudian menyerahkannya kepada jq; CBOR juga boleh melalui alat notasi diagnostik untuk menjadi teks boleh dibaca. Mengekalkan laluan debug teks lebih murah daripada memasang perkakasan atas permintaan.