{"id":20094568,"url":"https://github.com/denostack/superserial","last_synced_at":"2025-05-06T04:32:39.303Z","repository":{"id":42441286,"uuid":"473835436","full_name":"denostack/superserial","owner":"denostack","description":"A comprehensive Serializer/Deserializer that can handle any data type.","archived":false,"fork":false,"pushed_at":"2024-04-18T02:12:50.000Z","size":119,"stargazers_count":37,"open_issues_count":5,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-18T00:11:57.739Z","etag":null,"topics":["deno","serialization","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/denostack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-03-25T01:59:27.000Z","updated_at":"2024-11-06T17:58:52.000Z","dependencies_parsed_at":"2024-04-15T14:31:17.408Z","dependency_job_id":"d5518a2d-1c1d-44fb-932c-09ca00b22ca7","html_url":"https://github.com/denostack/superserial","commit_stats":{"total_commits":51,"total_committers":1,"mean_commits":51.0,"dds":0.0,"last_synced_commit":"455d053f41a821d34f0f532e56c05b567a5df441"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denostack%2Fsuperserial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denostack%2Fsuperserial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denostack%2Fsuperserial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denostack%2Fsuperserial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denostack","download_url":"https://codeload.github.com/denostack/superserial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252622614,"owners_count":21778033,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","serialization","typescript"],"created_at":"2024-11-13T16:51:15.732Z","updated_at":"2025-05-06T04:32:38.985Z","avatar_url":"https://github.com/denostack.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# superserial \u003ca href=\"https://github.com/denostack\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/denostack/images/main/logo.svg\" width=\"160\" align=\"right\" /\u003e\u003c/a\u003e\n\n\u003cp\u003e\n  \u003ca href=\"https://github.com/denostack/superserial/actions\"\u003e\u003cimg alt=\"Build\" src=\"https://img.shields.io/github/actions/workflow/status/denostack/superserial/ci.yml?branch=main\u0026logo=github\u0026style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/denostack/superserial\"\u003e\u003cimg alt=\"Coverage\" src=\"https://img.shields.io/codecov/c/gh/denostack/superserial?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003cimg alt=\"License\" src=\"https://img.shields.io/npm/l/superserial.svg?style=flat-square\" /\u003e\n  \u003cimg alt=\"Language Typescript\" src=\"https://img.shields.io/badge/language-Typescript-007acc.svg?style=flat-square\" /\u003e\n  \u003cbr /\u003e\n  \u003ca href=\"https://jsr.io/@denostack/superserial\"\u003e\u003cimg alt=\"JSR version\" src=\"https://jsr.io/badges/@denostack/superserial?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://deno.land/x/superserial\"\u003e\u003cimg alt=\"Deno version\" src=\"https://deno.land/badge/superserial/version?style=flat-square\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/superserial\"\u003e\u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/superserial.svg?style=flat-square\u0026logo=npm\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://npmcharts.com/compare/superserial?minimal=true\"\u003e\u003cimg alt=\"Downloads\" src=\"https://img.shields.io/npm/dt/superserial.svg?style=flat-square\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nA comprehensive Serializer/Deserializer that can handle any data type.\n\n## Usage\n\n### with Deno\n\n```bash\ndeno add @denostack/superserial\n```\n\n```ts\nimport { Serializer } from \"@denostack/superserial\";\n\nconst serializer = new Serializer();\n\nconst nodes = [{ self: null as any, siblings: [] as any[] }, {\n  self: null as any,\n  siblings: [] as any[],\n}];\nnodes[0].self = nodes[0];\nnodes[0].siblings = nodes;\nnodes[1].self = nodes[1];\nnodes[1].siblings = nodes;\n\nconst serialized = serializer.serialize(nodes);\n\nconsole.log(serialized);\n// [$1,$2];{\"self\":$1,\"siblings\":$0};{\"self\":$2,\"siblings\":$0}\n```\n\n### with Node.js \u0026 Browser\n\n**Install**\n\n```bash\nnpm install superserial\n```\n\n```ts\nimport { Serializer } from \"superserial\";\n\n// Usage is as above :-)\n```\n\n## Index\n\n- [Built-in Objects](#built-in-objects)\n- [Circular Reference](#circular-reference)\n- [Class Support](#class-support)\n\n### Built-in Objects\n\n**Value Properties**\n\n- `NaN`\n- `Infinity`, `-Infinity`\n- `undefined`\n\n```ts\nserializer.serialize({\n  und: undefined,\n  nan: NaN,\n  inf: Infinity,\n  ninf: -Infinity,\n}); // {\"und\":undefined,\"nan\":NaN,\"inf\":Infinity,\"ninf\":-Infinity}\n```\n\n**Fundamental Objects**\n\n- `Symbol`\n\n**ETC**\n\n- `BigInt`\n- `Date`\n- `RegExp`\n- `Map`\n- `Set`\n\n```ts\nconst symbol = Symbol();\nserializer.serialize({\n  sym: symbol,\n  bigint: 100n,\n  date: new Date(),\n  regex: /abc/gmi,\n  map: new Map([[\"key1\", \"value1\"], [\"key2\", \"value2\"]]),\n  set: new Set([1, 2, 3, 4]),\n});\n// {\"sym\":$1,\"bigint\":100n,\"date\":$2,\"regex\":$3,\"map\":$4,\"set\":$5};Symbol();Date(1648740167514);/abc/gim;Map(\"key1\"=\u003e\"value1\",\"key2\"=\u003e\"value2\");Set(1,2,3,4)\n```\n\n### Circular Reference\n\nExisting JSON functions do not support circular references, but **superserial**\nhas solved this problem.\n\n```ts\nconst nodes = [{ self: null as any, siblings: [] as any[] }, {\n  self: null as any,\n  siblings: [] as any[],\n}];\nnodes[0].self = nodes[0];\nnodes[0].siblings = nodes;\nnodes[1].self = nodes[1];\nnodes[1].siblings = nodes;\n\nconst serialized = serializer.serialize(nodes);\n\nconsole.log(serialized);\n// [$1,$2];{\"self\":$1,\"siblings\":$0};{\"self\":$2,\"siblings\":$0}\n\nconst deserialized = serializer.deserialize(serialized) as typeof nodes;\n\nconsole.log(deserialized === deserialized[0].siblings); // true\nconsole.log(deserialized[0] === deserialized[0].self); // true\nconsole.log(deserialized === deserialized[1].siblings); // true\nconsole.log(deserialized[1] === deserialized[1].self); // true\n```\n\n**Circular Set \u0026 Map**\n\n```ts\nconst set = new Set();\nset.add(set);\n\nserializer.serialize(set); // Set($0)\n\nconst map = new Map();\nmap.set(map, map);\n\nserializer.serialize(map); // Map($0=\u003e$0)\n```\n\nDeserialization also works perfectly!\n\n```ts\nconst set = serializer.deserialize(\"Set($0)\");\n\nconsole.log(set === [...set][0]); // true\n\nconst map = serializer.deserialize(\"Map($0=\u003e$0)\");\n\nconsole.log(map === [...map.keys()][0]); // true\nconsole.log(map === map.get([...map.keys()][0])); // true\n```\n\n### Class Support\n\nClasses contain methods, getters, etc., but JSON doesn't fully support them.\n**superserial** includes features that make it easy to use.\n\nThe class to be used for `deserialize` is defined when the Serializer is\ncreated.\n\n```ts\nclass TestUser {\n  constructor(\n    public name?: string,\n    public age?: number,\n  ) {\n  }\n}\n\nconst serializer = new Serializer({ classes: { TestUser } });\n```\n\nSerializes the object and then deserializes it again. Since the original class\nobject is converted as it is, all getters and methods can be used as they are.\n\n```ts\nconst serialized = serializer.serialize(new TestUser(\"wan2land\", 20));\nconsole.log(serialized);\n// TestUser{\"name\":\"wan2land\",\"age\":20}\n\nconst user = serializer.deserialize(serialized);\nconsole.log(user); // TestUser { name: \"wan2land\", age: 20 }\n```\n\n#### Alias\n\nIf you want to serialize a class with a different name, you can use the\n`classes` option.\n\n```ts\nclass TestUser {\n  constructor(\n    public name?: string,\n    public age?: number,\n  ) {\n  }\n}\n\nconst serializer = new Serializer({\n  classes: {\n    AliasTestUser: TestUser,\n  },\n});\n```\n\n```ts\nconst serialized = serializer.serialize(new TestUser(\"wan2land\", 20));\nconsole.log(serialized);\n// AliasTestUser{\"name\":\"wan2land\",\"age\":20}   \u003c--- AliasTestUser\n\nconst user = serializer.deserialize(serialized);\nconsole.log(user); // TestUser { name: \"wan2land\", age: 20 }\n```\n\n#### toSerialize / toDeserialize\n\nPrivate variables can be converted using two special symbols (`toSerialize`,\n`toDeserialize`).\n\nWhen serializing(`serialize`), the object's data is created based on the\n`toSerialize` method. You can check the result of `toSerialize` by looking at\nthe serialized string.\n\nWhen deserializing(`deserialize`), it is impossible to create an object without\na constructor call. (ref.\n[No backdoor to access private](https://github.com/tc39/proposal-class-fields#no-backdoor-to-access-private))\nIf the `toDeserialize` method is included, a value can be injected through\n`toDeserialize` after calling the constructor.\n\n```ts\nimport {\n  Serializer,\n  toDeserialize,\n  toSerialize,\n} from \"https://deno.land/x/superserial/mod.ts\";\n\nclass TestUser {\n  #_age = 0;\n  constructor(public name: string) {\n    this.#_age = 0;\n  }\n\n  setAge(age: number) {\n    this.#_age = age;\n  }\n\n  getAge() {\n    return this.#_age;\n  }\n\n  [toSerialize]() {\n    return {\n      name: this.name,\n      age: this.#_age,\n    };\n  }\n\n  [toDeserialize](\n    value: {\n      name: string;\n      age: number;\n    },\n  ) {\n    this.name = value.name;\n    this.#_age = value.age;\n  }\n}\n\nconst serializer = new Serializer({ classes: { TestUser } });\n\n{\n  const user = new TestUser(\"wan2land\");\n  user.setAge(20);\n\n  console.log(serializer.serialize(user)); // TestUser{\"name\":\"wan2land\",\"age\":20}\n}\n{\n  const user = serializer.deserialize\u003cTestUser\u003e(\n    'TestUser{\"name\":\"wan2land\",\"age\":20}',\n  );\n  console.log(user); // TestUser { name: \"wan2land\" }\n  console.log(user.getAge()); // 20\n}\n```\n\n## Benchmark\n\nPlease see [benchmark results](.benchmark).\n\n## See also\n\n- [Creating Superserial](https://wan2.land/posts/2022/09/14/superserial/) - My\n  blog post about superserial. (Korean)\n- [SuperClosure](https://github.com/jeremeamia/super_closure) PHP Serialize\n  Library, superserial was inspired by this.\n- [flatted](https://github.com/WebReflection/flatted)\n- [lave](https://github.com/jed/lave)\n- [arson](https://github.com/benjamn/arson)\n- [devalue](https://github.com/Rich-Harris/devalue)\n- [superjson](https://github.com/blitz-js/superjson)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenostack%2Fsuperserial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenostack%2Fsuperserial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenostack%2Fsuperserial/lists"}