first commit
This commit is contained in:
85
docs/foundation/data/serialize/src/codec/json/json-decode.md
Normal file
85
docs/foundation/data/serialize/src/codec/json/json-decode.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user