User Rating 0.0 β˜…β˜…β˜…β˜…β˜…
Total Usage 0 times
Presets:
Is this tool helpful?

Your feedback helps us improve.

β˜… β˜… β˜… β˜… β˜…

About

Binary serialization of JavaScript data is a non-trivial operation. Native JSON.stringify produces UTF-16 text, not compact binary. This tool implements a tagged binary packing protocol: each value is prefixed with a 1-byte type tag followed by a variable-length size prefix (LEB128 varint) and the raw payload. Strings are encoded as UTF-8 via the Web TextEncoder API. Numbers use IEEE 754 Float64 (8 bytes, big-endian). Booleans collapse to a single byte. Arrays and objects are encoded recursively with an element count prefix. Incorrect binary packing causes data corruption, protocol mismatches, and silent deserialization failures in networked systems. This tool validates input, shows the exact byte layout, and lets you download the packed binary for inspection or integration testing.

Limitations: circular references are rejected. BigInt and Symbol types are not supported. Maximum input size is approximately 1 MB of JSON text. The packing format is a custom schema designed for clarity, not a standard like Protocol Buffers or MessagePack. Pro tip: compare the packed size against JSON.stringify output to quantify the byte savings for your specific data shape.

binary converter javascript binary data serialization hex dump binary packing arraybuffer data encoding type encoding

Formulas

The binary packing protocol encodes each JavaScript value as a tagged byte sequence. The general frame structure is:

Frame = T + L + V

Where T = type tag (1 byte), L = length prefix (LEB128 varint, 1 - 3 bytes), V = raw value payload.

Varint encoding uses LEB128 (Little-Endian Base 128). Each byte stores 7 data bits. The high bit indicates continuation:

byte = (n & 0x7F) | (n > 0x7F ? 0x80 : 0x00)

Numbers are encoded as IEEE 754 double-precision floating point (64 bits, big-endian):

value = (βˆ’1)s Γ— 2e βˆ’ 1023 Γ— (1 + f)

Where s = sign bit (1 bit), e = biased exponent (11 bits), f = fractional mantissa (52 bits). Total packed size for a composite value is computed recursively:

Stotal = nβˆ‘i=0 (1 + varint_len(Li) + Li)

Where n = number of elements, Li = payload length of element i, and varint_len returns the number of bytes needed to encode the length as a varint.

Reference Data

JS TypeType Tag (Hex)Tag (Dec)Payload FormatSize (Bytes)Notes
null0x000None1Tag only, no payload
Boolean (false)0x0110x002Tag + 1 byte
Boolean (true)0x0110x012Tag + 1 byte
Number (Int8)0x022IEEE 754 Float64 BE9Tag + 8 bytes always
Number (Float64)0x022IEEE 754 Float64 BE9All numbers use Float64
Number (NaN)0x0227FF80000000000009Canonical NaN encoding
Number (Infinity)0x0227FF00000000000009Positive infinity
String (empty)0x033Varint(0)2Tag + length varint
String (ASCII)0x033Varint(len) + UTF-82+n1 byte per ASCII char
String (Unicode)0x033Varint(len) + UTF-82-4+nMulti-byte UTF-8 sequences
Array0x044Varint(count) + elementsVariableRecursive encoding
Object0x055Varint(count) + key-value pairsVariableKeys encoded as strings
undefined0x066None1Tag only, no payload
Varint (1 byte)Size ≀ 1270xxxxxxx1High bit = 0 means final
Varint (2 bytes)Size ≀ 163831xxxxxxx 0xxxxxxx2LEB128 continuation bit
Varint (3 bytes)Size ≀ 20971511xxxxxxx 1xxxxxxx 0xxxxxxx3Max supported length
IEEE 754 Float64Sign 1 bitExponent 11 bits + Mantissa 52 bits8Big-endian byte order
UTF-8 (1-byte)U+0000 to U+007F0xxxxxxx1ASCII compatible
UTF-8 (2-byte)U+0080 to U+07FF110xxxxx 10xxxxxx2Latin, Greek, Cyrillic
UTF-8 (3-byte)U+0800 to U+FFFF1110xxxx 10xxxxxx 10xxxxxx3CJK, most symbols
UTF-8 (4-byte)U+10000 to U+10FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx4Emoji, rare scripts

Frequently Asked Questions

All JavaScript numbers are encoded as IEEE 754 Float64 (8 bytes, big-endian). NaN maps to the canonical representation 0x7FF8000000000000. Positive Infinity maps to 0x7FF0000000000000. Negative Infinity maps to 0xFFF0000000000000. These are standard IEEE 754 special values and will be correctly decoded by any system that reads Float64.
Strings are encoded as UTF-8 via the Web TextEncoder API. ASCII characters use 1 byte. Characters in the range U+0080 to U+07FF use 2 bytes. CJK characters and most symbols use 3 bytes. Emoji and supplementary plane characters use 4 bytes. The length prefix stores the byte count of the UTF-8 encoding, not the character count. This means a 3-character emoji string might occupy 12 payload bytes.
Yes. The format is self-describing: each frame starts with a type tag that tells the decoder what follows. The varint length prefix provides exact payload boundaries. A decoder reads the tag, determines the type, reads the length, extracts the payload, and reconstructs the value. For arrays and objects, decoding proceeds recursively. The tool displays the complete byte layout so you can implement a decoder in any language.
Fixed-length prefixes waste space. A 4-byte uint32 prefix adds 4 bytes even for a 3-character string. LEB128 uses 1 byte for sizes up to 127, 2 bytes up to 16383, and 3 bytes up to 2097151. For typical JSON data where most strings and arrays are small, varint encoding saves 2-3 bytes per field. Over thousands of fields in a dataset, this compounds significantly.
Circular references cause infinite recursion during encoding. The tool detects circular references by maintaining a Set of visited object references during recursive traversal. If a previously seen reference is encountered, encoding stops and an error toast is displayed. You must break the cycle before encoding. JSON.stringify has the same limitation.
The practical limit is approximately 1 MB of JSON text input. This is constrained by browser memory for ArrayBuffer allocation and DOM rendering of the hex dump. For a hex dump, each byte generates roughly 4 characters of display text, so a 1 MB binary output would produce a 4 MB hex string. Beyond this, the browser tab may become unresponsive. For large datasets, consider a streaming binary serializer.