CBOR, MessagePack a BSON

Binární formáty ukládají strukturovaná data v bajtech a mohou podporovat typy navíc. Nejsou pouze JSON text v jiném kódování a nejsou vždy menší než komprimovaný JSON.

Autor: Aktualizováno

CBOR

CBOR standardizuje RFC 8949. Má celá čísla, byte strings, text, pole, mapy a tagy. Mapa může mít jiné klíče než řetězce. Pro podpis nebo otisk je potřeba konkrétní deterministický profil; obyčejné opakované kódování nemusí dát stejné bajty.

CBOR
JSON: {"a":1}
CBOR (hex): a1 61 61 01

MessagePack

MessagePack má vlastní rodiny integer, string, binary, array, map a extension. Extension typy vyžadují dohodu implementací. Bajty CBOR nemůžeš předat MessagePack dekodéru jen proto, že oba ukládají mapy.

MessagePack
JSON: {"a":1}
MessagePack (hex): 81 a1 61 01

BSON

BSON používá dokumenty s řetězcovými jmény a typovanými hodnotami. Obsahuje například ObjectId, datetime, int64 a decimal128. Převod na obyčejný JSON musí pro tyto typy definovat reprezentaci; Extended JSON je samostatná konvence.

Co změřit a otestovat

Protocol Buffers na rozdíl od CBOR a MessagePack vyžaduje schéma (.proto) a používá ho gRPC, viz REST vs. gRPC. Porovnej velikost s kompresí, čas a podporu typů v obou jazycích. Omez délky, hloubku a neznámé extension/tagy. Zpětný převod přes JavaScript Number nemusí zachovat všechna 64bitová celá čísla. Výukové hex příklady vyzkoušej v odpovídajícím nástroji.

CBOR · MessagePack

Stejná data ve dvou kodecích Node.js

binary-demo.mjs — npm install cborg @msgpack/msgpack
import {encode as cborEncode, decode as cborDecode} from "cborg";
import {encode as packEncode, decode as packDecode} from "@msgpack/msgpack";
const data = {a: 1};
const hex = bytes => Buffer.from(bytes).toString("hex");
const cbor = cborEncode(data);
const pack = packEncode(data);
console.log("CBOR", hex(cbor), cborDecode(cbor));
console.log("MessagePack", hex(pack), packDecode(pack));

Výstup obsahuje CBOR a1616101 a MessagePack 81a16101; oba dekodéry obnoví objekt s a=1. Vlož hex do odpovídajícího CBOR nebo MessagePack nástroje. Jde o jiné bajty pro podobný datový model, nikoli dvě textová kódování JSON.

Byte string je například Uint8Array, ne řetězec Base64. Při převodu do obyčejného JSON proto stanov reprezentaci. Velké integer mohou vyžadovat BigInt nebo jiný přesný typ knihovny; JSON.stringify na BigInt běžně selže. CBOR tagy a MessagePack extension mohou vyžadovat společnou registraci významu na obou stranách.

BSON a Extended JSON

Canonical Extended JSON — reprezentace typů BSON
{"_id":{"$oid":"507f1f77bcf86cd799439011"},"castka":{"$numberDecimal":"12.50"},"cas":{"$date":{"$numberLong":"0"}}}

Obálky $oid, $numberDecimal a $date nejsou obecné typy standardního JSON. Parser JSON je načte jako obyčejné objekty; interpretaci zajišťuje BSON/EJSON knihovna. Při přenosu jen hodnoty 12.50 jako Number bys ztratil desetinný typ a někdy přesnost. Relaxed a canonical Extended JSON mají odlišný účel, proto pojmenuj použitý profil.

Pro srovnání výkonu použij stejná reprezentativní data, identické aplikační typy a přenos s případnou kompresí. Hex výpis je dvakrát delší text než počet bajtů, takže podle délky hexu neporovnávej velikost binárního přenosu. Specifikace: CBOR, MessagePack a MongoDB Extended JSON.