3.2 KiB
3.2 KiB
json-decode
Purpose
Implements deserialize, the inverse of serialize. Given a tagged JSON string produced by the encoder, it reconstructs the original JavaScript value graph including all registered types (built-ins and custom), undefined, NaN, and ±Infinity. Any __t tag that has no registered handler causes an UnsupportedTypeError to be thrown immediately rather than silently discarding data.
The decoder is intentionally strict: it is safer to fail loudly on an unrecognised tag than to silently drop values, which could cause subtle data corruption downstream.
Features
- Full inverse of
serialize: all built-in type tags are decoded back to their original JavaScript types AbortSignalsupport for cancelling mid-traversal on large payloads, checked every 256 nodesUnsupportedTypeErrorthrown (with the tag name incontext.tag) for unrecognised__tvalues- Recursive array and plain-object decoding
- Zero allocations for pass-through primitives (string, number, boolean, null)
Usage: Basic Example
import { deserialize, serialize } from "@suaveplan/serialize";
const original = { created: new Date(), tags: new Set(["x", "y"]) };
const json = serialize(original);
const restored = deserialize(json) as typeof original;
restored.created instanceof Date; // true
restored.tags instanceof Set; // true
Usage: Advanced Example
import { deserialize, UnsupportedTypeError } from "@suaveplan/serialize";
const controller = new AbortController();
// Cancel deserialization partway through:
setTimeout(() => controller.abort(new Error("timeout")), 10);
try {
const value = deserialize(largeJson, { signal: controller.signal });
processValue(value);
} catch (err) {
if (err instanceof UnsupportedTypeError) {
console.error("Unknown type tag:", err.context?.tag);
} else {
// likely the abort reason
throw err;
}
}
API Reference
deserialize(json: string, opts?: DeserializeOptions): unknown
Parse json and recursively reconstruct the JavaScript value it encodes.
Parameters:
json— a tagged JSON string produced byserializeopts.signal— anAbortSignal; checked every 256 nodes
Returns: the reconstructed value.
Throws:
UnsupportedTypeErrorwhen a__ttag has no registered decoderSyntaxErrorfromJSON.parseif the input is not valid JSON- The
AbortSignal's reason whensignalis aborted
DeserializeOptions
interface DeserializeOptions {
signal?: AbortSignal;
}
Implementation Notes
- The decoder calls
JSON.parseonce at the top level and then recursively traverses the parsed intermediate tree. This avoids parsing partial JSON strings and keeps the implementation simple. - For tagged objects, the inner
vpayload is decoded recursively before being handed todef.decode. This means registered type decoders always receive already-decoded JavaScript values, not raw JSON intermediates. - Signal checking is shared with a module-level counter that resets per
deserializecall; it fires every 256 traversed nodes. - The decoder does not validate the structure of
vbeyond callingdef.decode; responsibility for validating the payload shape belongs to each registered type definition.