@denostack/superserial@0.3.5
latest
This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




JSR Score
58%
Published
a year ago (0.3.5)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309# superserial <a href="https://github.com/denostack"><img src="https://raw.githubusercontent.com/denostack/images/main/logo.svg" width="160" align="right" /></a> <p> <a href="https://github.com/denostack/superserial/actions"><img alt="Build" src="https://img.shields.io/github/actions/workflow/status/denostack/superserial/ci.yml?branch=main&logo=github&style=flat-square" /></a> <a href="https://codecov.io/gh/denostack/superserial"><img alt="Coverage" src="https://img.shields.io/codecov/c/gh/denostack/superserial?style=flat-square" /></a> <img alt="License" src="https://img.shields.io/npm/l/superserial.svg?style=flat-square" /> <img alt="Language Typescript" src="https://img.shields.io/badge/language-Typescript-007acc.svg?style=flat-square" /> <br /> <a href="https://jsr.io/@denostack/superserial"><img alt="JSR version" src="https://jsr.io/badges/@denostack/superserial?style=flat-square" /></a> <a href="https://deno.land/x/superserial"><img alt="Deno version" src="https://deno.land/badge/superserial/version?style=flat-square" /></a> <a href="https://www.npmjs.com/package/superserial"><img alt="NPM Version" src="https://img.shields.io/npm/v/superserial.svg?style=flat-square&logo=npm" /></a> <a href="https://npmcharts.com/compare/superserial?minimal=true"><img alt="Downloads" src="https://img.shields.io/npm/dt/superserial.svg?style=flat-square" /></a> </p> A comprehensive Serializer/Deserializer that can handle any data type. ## Usage ### with Deno ```bash deno add @denostack/superserial ``` ```ts import { Serializer } from "@denostack/superserial"; const serializer = new Serializer(); const nodes = [{ self: null as any, siblings: [] as any[] }, { self: null as any, siblings: [] as any[], }]; nodes[0].self = nodes[0]; nodes[0].siblings = nodes; nodes[1].self = nodes[1]; nodes[1].siblings = nodes; const serialized = serializer.serialize(nodes); console.log(serialized); // [$1,$2];{"self":$1,"siblings":$0};{"self":$2,"siblings":$0} ``` ### with Node.js & Browser **Install** ```bash npm install superserial ``` ```ts import { Serializer } from "superserial"; // Usage is as above :-) ``` ## Index - [Built-in Objects](#built-in-objects) - [Circular Reference](#circular-reference) - [Class Support](#class-support) ### Built-in Objects **Value Properties** - `NaN` - `Infinity`, `-Infinity` - `undefined` ```ts serializer.serialize({ und: undefined, nan: NaN, inf: Infinity, ninf: -Infinity, }); // {"und":undefined,"nan":NaN,"inf":Infinity,"ninf":-Infinity} ``` **Fundamental Objects** - `Symbol` **ETC** - `BigInt` - `Date` - `RegExp` - `Map` - `Set` ```ts const symbol = Symbol(); serializer.serialize({ sym: symbol, bigint: 100n, date: new Date(), regex: /abc/gmi, map: new Map([["key1", "value1"], ["key2", "value2"]]), set: new Set([1, 2, 3, 4]), }); // {"sym":$1,"bigint":100n,"date":$2,"regex":$3,"map":$4,"set":$5};Symbol();Date(1648740167514);/abc/gim;Map("key1"=>"value1","key2"=>"value2");Set(1,2,3,4) ``` ### Circular Reference Existing JSON functions do not support circular references, but **superserial** has solved this problem. ```ts const nodes = [{ self: null as any, siblings: [] as any[] }, { self: null as any, siblings: [] as any[], }]; nodes[0].self = nodes[0]; nodes[0].siblings = nodes; nodes[1].self = nodes[1]; nodes[1].siblings = nodes; const serialized = serializer.serialize(nodes); console.log(serialized); // [$1,$2];{"self":$1,"siblings":$0};{"self":$2,"siblings":$0} const deserialized = serializer.deserialize(serialized) as typeof nodes; console.log(deserialized === deserialized[0].siblings); // true console.log(deserialized[0] === deserialized[0].self); // true console.log(deserialized === deserialized[1].siblings); // true console.log(deserialized[1] === deserialized[1].self); // true ``` **Circular Set & Map** ```ts const set = new Set(); set.add(set); serializer.serialize(set); // Set($0) const map = new Map(); map.set(map, map); serializer.serialize(map); // Map($0=>$0) ``` Deserialization also works perfectly! ```ts const set = serializer.deserialize("Set($0)"); console.log(set === [...set][0]); // true const map = serializer.deserialize("Map($0=>$0)"); console.log(map === [...map.keys()][0]); // true console.log(map === map.get([...map.keys()][0])); // true ``` ### Class Support Classes contain methods, getters, etc., but JSON doesn't fully support them. **superserial** includes features that make it easy to use. The class to be used for `deserialize` is defined when the Serializer is created. ```ts class TestUser { constructor( public name?: string, public age?: number, ) { } } const serializer = new Serializer({ classes: { TestUser } }); ``` Serializes the object and then deserializes it again. Since the original class object is converted as it is, all getters and methods can be used as they are. ```ts const serialized = serializer.serialize(new TestUser("wan2land", 20)); console.log(serialized); // TestUser{"name":"wan2land","age":20} const user = serializer.deserialize(serialized); console.log(user); // TestUser { name: "wan2land", age: 20 } ``` #### Alias If you want to serialize a class with a different name, you can use the `classes` option. ```ts class TestUser { constructor( public name?: string, public age?: number, ) { } } const serializer = new Serializer({ classes: { AliasTestUser: TestUser, }, }); ``` ```ts const serialized = serializer.serialize(new TestUser("wan2land", 20)); console.log(serialized); // AliasTestUser{"name":"wan2land","age":20} <--- AliasTestUser const user = serializer.deserialize(serialized); console.log(user); // TestUser { name: "wan2land", age: 20 } ``` #### toSerialize / toDeserialize Private variables can be converted using two special symbols (`toSerialize`, `toDeserialize`). When serializing(`serialize`), the object's data is created based on the `toSerialize` method. You can check the result of `toSerialize` by looking at the serialized string. When deserializing(`deserialize`), it is impossible to create an object without a constructor call. (ref. [No backdoor to access private](https://github.com/tc39/proposal-class-fields#no-backdoor-to-access-private)) If the `toDeserialize` method is included, a value can be injected through `toDeserialize` after calling the constructor. ```ts import { Serializer, toDeserialize, toSerialize, } from "https://deno.land/x/superserial/mod.ts"; class TestUser { #_age = 0; constructor(public name: string) { this.#_age = 0; } setAge(age: number) { this.#_age = age; } getAge() { return this.#_age; } [toSerialize]() { return { name: this.name, age: this.#_age, }; } [toDeserialize]( value: { name: string; age: number; }, ) { this.name = value.name; this.#_age = value.age; } } const serializer = new Serializer({ classes: { TestUser } }); { const user = new TestUser("wan2land"); user.setAge(20); console.log(serializer.serialize(user)); // TestUser{"name":"wan2land","age":20} } { const user = serializer.deserialize<TestUser>( 'TestUser{"name":"wan2land","age":20}', ); console.log(user); // TestUser { name: "wan2land" } console.log(user.getAge()); // 20 } ``` ## Benchmark Please see [benchmark results](.benchmark). ## See also - [Creating Superserial](https://wan2.land/posts/2022/09/14/superserial/) - My blog post about superserial. (Korean) - [SuperClosure](https://github.com/jeremeamia/super_closure) PHP Serialize Library, superserial was inspired by this. - [flatted](https://github.com/WebReflection/flatted) - [lave](https://github.com/jed/lave) - [arson](https://github.com/benjamn/arson) - [devalue](https://github.com/Rich-Harris/devalue) - [superjson](https://github.com/blitz-js/superjson)