Skip to content

JSON serializer

JsonSerializer is the default serializer. Standard JSON via JSON.stringify + JSON.parse; bytes are UTF-8.

import { JsonSerializer } from 'actor-ts';
const serializer = new JsonSerializer();
const bytes = serializer.toBinary({ kind: 'inc', n: 1 });
// → Uint8Array of '{"kind":"inc","n":1}' as UTF-8
const decoded = serializer.fromBinary(bytes, '');
// → { kind: 'inc', n: 1 }
  • Universal — every language has a JSON parser.
  • Human-readable — open a journal file with cat; see the events.
  • Schema-flexible — no compile step; types evolve via ordinary code changes (+ schema-migration adapters).
  • Battle-tested — every Web API speaks JSON.

For most apps, you’ll never change serializers — JSON covers it.

  • Plain objects, arrays.
  • Strings, numbers, booleans, null.
  • Nested combinations.

What gets dropped or transformed:

TypeBehavior
undefinedDropped from objects / arrays.
DateStringified via toISOString(); round-trips as string.
Map / SetSerialized as empty {}.
BigIntThrows TypeError.
FunctionDropped (in objects); arrays become null.
SymbolDropped.
Class instancesSerialized as plain { ...fields }; methods lost.

For most actor messages, this is fine — the framework’s message conventions already discourage non-serializable shapes.

JSON is larger than binary formats for the same data:

  • Numbers are decimal strings ("42" is 4 bytes vs CBOR’s 2).
  • Field names are repeated (every record has "kind":"...").
  • Binary data (Uint8Array) base64-encodes (33 % overhead).

For text-heavy or repetitive data, JSON’s overhead is small. For binary-heavy data (images, encoded payloads), CBOR saves meaningfully.

Rough numbers per serialize/deserialize pair:

  • Small object (~50 bytes): ~1-2 microseconds.
  • Medium object (~1 KB): ~5-15 microseconds.
  • Large object (~100 KB): ~1-2 ms.

JSON.parse / JSON.stringify are native code in V8/JSC — fast enough that JSON serialization is rarely the bottleneck.

Need to interop with non-JSON systems? → Custom (Protobuf/Avro)
Bandwidth-bound (large or many small messages)? → CBOR
Need typed schemas in source control? → Custom (Protobuf)
Otherwise → Stay on JSON

Most production apps stay on JSON for the actor wire and persistence — the perf / size gains from switching rarely justify the operational complexity.