https://github.com/katt/danson
https://github.com/katt/danson
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/katt/danson
- Owner: KATT
- License: mit
- Created: 2025-06-13T12:32:20.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-12-20T00:59:14.000Z (6 months ago)
- Last Synced: 2025-12-22T10:59:00.038Z (6 months ago)
- Language: TypeScript
- Size: 218 KB
- Stars: 10
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE.md
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
danSON
Progressive JSON
## About
danSON is a progressive JSON serializer and deserializer that can serialize and deserialize arbitrary objects into JSON.
## Features
- Streaming of `Promise`s, `AsyncIterable`s, and `ReadableStream`s
- Custom serializers / deserializers
- De-duplication of objects (optional)
- Circular references
- Serializable errors
- Human-readable JSON output
- Built-in serializers for common JavaScript types
## Installation
```shell
npm install danson
```
[Try the example on StackBlitz](https://stackblitz.com/github/KATT/danson/tree/main/example)
## Usage
### Synchronous Usage
```ts
import { parseSync, stringifySync } from "danson";
const data = {
foo: "bar",
};
const stringified = stringifySync(data);
const parsed = parseSync(stringified);
console.log(parsed); // { foo: "bar" }
```
### Asynchronous Usage
```ts
import { parseAsync, stringifyAsync } from "danson";
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const data = {
promise: (async () => {
await sleep(1000);
return "hello promise";
})(),
};
const iterable = stringifyAsync(data);
const parsed = await parseAsync(iterable);
// ^? { promise: Promise }
console.log(await parsed.promise); // "hello promise"
```
### Built-in Serializers
The `std` module provides built-in serializers for common JavaScript types that works with both synchronous and asynchronous usage.
Supported types:
- `BigInt`
- `Date`
- `Headers`
- `Map`
- Special numbers (`-0`, `Infinity`, `-Infinity`, `NaN`)
- `RegExp`
- `Set`
- TypedArrays (`Int8Array`, `Uint8Array`, etc.)
- `undefined`
- `URL`
- `URLSearchParams`
```ts
import { parseSync, std, stringifySync } from "danson";
// Using built-in serializers
const data = {
date: new Date(),
headers: new Headers({
"Content-Type": "application/json",
}),
map: new Map([["key", "value"]]),
numbers: {
bigint: 123n,
infinity: Infinity,
negativeInfinity: -Infinity,
negativeZero: -0,
notANumber: NaN,
},
regexp: /foo/g,
set: new Set([1, 2, 3]),
typedArray: new Int8Array([1, 2, 3]),
undef: undefined,
url: new URL("https://example.com"),
urlSearchParams: new URLSearchParams("foo=bar"),
};
const stringified = stringifySync(data, {
serializers: {
...std.serializers,
// ... your custom serializers
},
space: 2,
});
const parsed = parseSync(stringified, {
deserializers: {
...std.deserializers,
// ... your custom deserializers
},
});
```
### Custom Serialization
You can provide custom serializers for your own types.
```ts
import { Temporal } from "@js-temporal/polyfill";
import { std } from "danson";
const stringified = stringifySync(value, {
serializers: {
...std.serializers, // use the built-in serializers (optional)
"Temporal.Instant": (value) =>
value instanceof Temporal.Instant ? value.toJSON() : false,
},
});
const parsed = parseSync(stringified, {
deserializers: {
...std.deserializers, // use the built-in deserializers (optional)
"Temporal.Instant": (value) => Temporal.Instant.from(value as string),
},
});
```
#### `TransformerPair`
Type utility for defining serializer/deserializer pairs.
Used internally but can be useful for type-safe custom serializers.
```ts
import { Temporal } from "@js-temporal/polyfill";
import { TransformerPair } from "danson";
// Define a type-safe transformer pair for Temporal.Instant
type TemporalNow = TransformerPair;
const serializeTemporalNow: TemporalNow["serialize"] = (value) => {
if (value instanceof Temporal.Instant) {
return value.toJSON();
}
return false;
};
const deserializeTemporalNow: TemporalNow["deserialize"] = (value) => {
return Temporal.Instant.from(value);
};
// Use the transformer pair
const source = {
instant: Temporal.Now.instant(),
};
const stringified = stringifySync(source, {
serializers: {
"Temporal.Instant": serializeTemporalNow,
},
});
const result = parseSync(stringified, {
deserializers: {
"Temporal.Instant": deserializeTemporalNow,
},
});
```
## Example outputs
### Streaming `Promise`s
#### Promise example input
```ts
const source = {
foo: "bar",
promise: (async () => {
await sleep(1000);
return "hello promise";
})(),
};
const stringified = stringifySync(source, {
space: 2,
});
for await (const chunk of stringified) {
console.log(chunk);
}
```
#### Promise example output
```jsonc
{
"json": {
"foo": "bar",
"promise": {
"_": "$", // informs the deserializer that this is a special type
"type": "Promise", // it is a Promise
"value": 1, // index of the Promise that will come later
}
}
}
```
```jsonc
[
1, // index of the Promise
0, // Promise succeeded (0 = success, 1 = failure)
{
"json": "hello promise"
}
]
```
### Streaming `AsyncIterable`s
#### AsyncIterable example input
```ts
const source = {
asyncIterable: (async function* () {
yield "hello";
yield "world";
return "done";
})(),
};
const stringified = stringifySync(source, {
space: 2,
});
for await (const chunk of stringified) {
console.log(chunk);
}
```
#### AsyncIterable example output
```jsonc
{
"json": {
"foo": "bar",
"asyncIterable": {
"_": "$",
"type": "AsyncIterable",
"value": 0
}
}
}
```
```jsonc
[
0,
0,
{
"json": "world"
}
]
```
```jsonc
[
0, // index of the AsyncIterable
2,
{
"json": "done"
}
]
```
## API Reference
### `stringifySync(value: unknown, options?: StringifyOptions): string`
Serializes a value into a JSON string.
### `parseSync(value: string, options?: ParseOptions): T`
Deserializes a JSON string into a value.
### `serializeSync(value: unknown, options?: StringifyOptions): SerializeReturn`
Serializes a value into a `JSON.stringify`-compatible format.
### `deserializeSync(value: SerializeReturn, options?: ParseOptions): T`
Deserializes from a `SerializeReturn` object into a value.
### `stringifyAsync(value: unknown, options?: StringifyOptions): AsyncIterable`
Serializes a value into a stream of JSON strings asynchronously.
### `parseAsync(value: AsyncIterable, options?: ParseOptions): Promise`
Deserializes a stream of JSON strings into a value asynchronously.
### `serializeAsync(value: unknown, options?: StringifyOptions): AsyncIterable`
Serializes a value into a stream of intermediate objects asynchronously.
### `deserializeAsync(value: AsyncIterable, options?: ParseOptions): Promise`
Deserializes a stream of intermediate objects into a value asynchronously.