# 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 - `AbortSignal` support for cancelling mid-traversal on large payloads, checked every 256 nodes - `UnsupportedTypeError` thrown (with the tag name in `context.tag`) for unrecognised `__t` values - Recursive array and plain-object decoding - Zero allocations for pass-through primitives (string, number, boolean, null) ## Usage: Basic Example ```typescript 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 ```typescript 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 by `serialize` - `opts.signal` — an `AbortSignal`; checked every 256 nodes **Returns:** the reconstructed value. **Throws:** - `UnsupportedTypeError` when a `__t` tag has no registered decoder - `SyntaxError` from `JSON.parse` if the input is not valid JSON - The `AbortSignal`'s reason when `signal` is aborted ### `DeserializeOptions` ```typescript interface DeserializeOptions { signal?: AbortSignal; } ``` ## Implementation Notes - The decoder calls `JSON.parse` once 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 `v` payload is decoded recursively *before* being handed to `def.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 `deserialize` call; it fires every 256 traversed nodes. - The decoder does not validate the structure of `v` beyond calling `def.decode`; responsibility for validating the payload shape belongs to each registered type definition.