@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)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363import { assertEquals, assertInstanceOf, assertNotStrictEquals, assertStrictEquals, } from "jsr:@std/assert@^0.222.1"; import { assertSpyCall, spy } from "jsr:/@std/testing@^0.222.1/mock"; import { deserialize } from "./deserialize.ts"; import { toDeserialize } from "./symbol.ts"; Deno.test("deserialize scalar", () => { assertEquals(deserialize("null"), null); assertEquals(deserialize("undefined"), undefined); assertEquals(deserialize("true"), true); assertEquals(deserialize("false"), false); assertEquals(deserialize("30"), 30); assertEquals(deserialize("30.1"), 30.1); assertEquals(deserialize("30n"), 30n); assertEquals(deserialize("-30n"), -30n); assertEquals(deserialize("9007199254740991000000n"), 9007199254740991000000n); assertEquals( deserialize("-9007199254740991000000n"), -9007199254740991000000n, ); assertEquals(deserialize('"string"'), "string"); }); Deno.test("deserialize string with escape", () => { assertEquals(deserialize('"\\\\"'), "\\"); assertEquals(deserialize('"\\\\x00"'), "\\x00"); assertEquals(deserialize('"\\u0000"'), "\x00"); }); Deno.test("deserialize extend scalar", () => { assertEquals(deserialize("NaN"), NaN); assertEquals(deserialize("Infinity"), Infinity); assertEquals(deserialize("-Infinity"), -Infinity); }); Deno.test("deserialize symbol", () => { const symbol1 = deserialize<symbol>("Symbol()"); assertEquals(typeof symbol1, "symbol"); assertEquals(symbol1.description, undefined); const symbol2 = deserialize<symbol>('Symbol("desc1")'); assertEquals(typeof symbol2, "symbol"); assertEquals(symbol2.description, "desc1"); const deserialized = deserialize<[symbol, symbol, symbol, [symbol]]>( '[$1,$2,$3,$4];Symbol("sym1");Symbol("sym2");Symbol("sym1");[$2]', ); assertEquals(deserialized[0].description, "sym1"); assertEquals(deserialized[1].description, "sym2"); assertEquals(deserialized[2].description, "sym1"); assertNotStrictEquals(deserialized[0], deserialized[2]); assertStrictEquals( deserialized[1], deserialized[3][0], ); }); Deno.test("deserialize built-in Set", () => { assertEquals( deserialize("Set(1,2,3,4,5)"), new Set([1, 2, 3, 4, 5]), ); }); Deno.test("deserialize built-in Set circular", () => { const deserialized = deserialize<Set<unknown>>("Set($0)"); assertStrictEquals( deserialized, [...deserialized][0], ); }); Deno.test("deserialize built-in Map", () => { assertEquals( deserialize( 'Map("string"=>"this is string",true=>"boolean",null=>"null",$1=>"object");{}', ), new Map<unknown, unknown>([ ["string", "this is string"], [true, "boolean"], [null, "null"], [{}, "object"], ]), ); }); Deno.test("deserialize build-in Map deep", () => { const map1 = new Map([["key1_1", "value1_1"], ["key1_2", "value1_2"]]); const map2 = new Map([["key2_1", "value2_1"], ["key2_2", "value2_2"]]); assertEquals( deserialize( 'Map("key1"=>$1,$2=>"val2");Map("key1_1"=>"value1_1","key1_2"=>"value1_2");Map("key2_1"=>"value2_1","key2_2"=>"value2_2")', ), new Map<unknown, unknown>([ ["key1", map1] as const, [map2, "val2"] as const, ]), ); }); Deno.test("deserialize build-in Map circular", () => { const map1 = deserialize("Map($0=>$0)") as Map<unknown, unknown>; const keys1 = [...map1.keys()]; assertEquals(keys1.length, 1); assertStrictEquals(keys1[0], map1); assertStrictEquals(map1.get(map1), map1); const map2 = deserialize('Map($0=>"val","key"=>$0)') as Map<unknown, unknown>; const keys2 = [...map2.keys()]; assertEquals(keys2.length, 2); assertStrictEquals(map2.get(map2), "val"); assertStrictEquals(map2.get("key"), map2); }); Deno.test("deserialize array", () => { assertEquals(deserialize("[]"), []); assertEquals( deserialize( '[$1,$2,$3];[$4,$5];[1,2];[1];[$6,2,"",false,$7];[$8];{};[];[]', ), [[[{}, 2, "", false, []], [[]]], [1, 2], [1]], ); assertEquals( deserialize('[$1,$2];{"name":"wan2land"};{"name":"wan3land"}'), [{ name: "wan2land" }, { name: "wan3land" }], ); assertEquals( deserialize('{"users":$1};[$2,$3];{"name":"wan2land"};{"name":"wan3land"}'), { users: [{ name: "wan2land" }, { name: "wan3land" }] }, ); // also support json assertEquals( deserialize('[{"name":"wan2land"},{"name":"wan3land"}]'), [{ name: "wan2land" }, { name: "wan3land" }], ); }); Deno.test("deserialize object", () => { assertEquals(deserialize("{}"), {}); assertEquals(deserialize('{"foo":"foo string","und":undefined}'), { foo: "foo string", und: undefined, }); assertEquals( deserialize('{"string":$1,"true":$2,"false":$3};"string";true;false'), { string: "string", true: true, false: false }, ); }); Deno.test("deserialize object self circular", () => { const result = deserialize<{ boolean: false; self: unknown }>( '{"boolean":false,"self":$0}', ); assertEquals(result.boolean, false); assertStrictEquals(result.self, result); }); Deno.test("deserialize object circular", () => { const result = deserialize< { children: { parent: unknown; sibling: unknown }[] } >( '{"children":[$1,$2]};{"parent":$0,"sibling":$2};{"parent":$0,"sibling":$1}', ); assertStrictEquals(result.children[0].parent, result); assertStrictEquals(result.children[1].parent, result); assertStrictEquals(result.children[0].sibling, result.children[1]); assertStrictEquals(result.children[1].sibling, result.children[0]); }); Deno.test("deserialize class object", () => { class TestUser { age = 0; constructor(public name: string) { } } const spyConsole = spy(console, "warn"); const deserialized = deserialize( 'TestUser{"name":"wan2land","age":20}', { classes: { TestUser } }, ) as TestUser; assertInstanceOf(deserialized, TestUser); assertEquals(deserialized.name, "wan2land"); assertEquals(deserialized.age, 20); assertEquals(spyConsole.calls.length, 0); spyConsole.restore(); }); Deno.test("deserialize class object with loadClass", () => { class TestUser { age = 0; constructor(public name: string) { } } const loadClass = spy((name: string) => { if (name === "TestUser") { return TestUser; } return null; }); const deserialized = deserialize( 'TestUser{"name":"wan2land","age":20}', { loadClass, }, ) as TestUser; assertInstanceOf(deserialized, TestUser); assertEquals(deserialized.name, "wan2land"); assertEquals(deserialized.age, 20); assertEquals(loadClass.calls.length, 1); }); Deno.test("deserialize class object undefined", () => { const spyConsole = spy(console, "warn"); assertEquals( deserialize( 'TestUser{"name":"wan2land","age":20}', ), { name: "wan2land", age: 20, }, ); assertSpyCall( spyConsole, 0, { args: [ "Class TestUser is not defined. It will be ignored.", ], }, ); spyConsole.restore(); }); Deno.test("deserialize class with private", () => { class TestUser { #_age = 0; constructor(public name: string) { this.#_age = 0; } setAge(age: number) { this.#_age = age; } getAge() { return this.#_age; } [toDeserialize]( value: { name: string; age: number; }, ) { this.name = value.name; this.#_age = value.age; } } const spyConsole = spy(console, "warn"); const deserialized = deserialize( 'TestUser{"name":"wan2land","age":20}', { classes: { TestUser } }, ) as TestUser; assertInstanceOf(deserialized, TestUser); assertEquals(deserialized.name, "wan2land"); assertEquals(deserialized.getAge(), 20); assertEquals(spyConsole.calls.length, 0); spyConsole.restore(); }); Deno.test("deserialize class with private", () => { class User { #comments: Comment[] = []; constructor(public name: string) { } [toDeserialize]( value: { name: string; comments: Comment[]; }, ) { this.name = value.name; this.#comments = value.comments; } writeComment(text: string) { this.#comments.push(new Comment(text)); } getComments() { return this.#comments; } } class Comment { constructor(public text: string) {} } const deserialized = deserialize( 'User{"name":"wan2land","comments":$1};[$2,$3];Comment{"text":"hello world 1"};Comment{"text":"hello world 2"}', { classes: { User, Comment, }, }, ) as User; assertInstanceOf(deserialized, User); assertEquals(deserialized.name, "wan2land"); const comments = deserialized.getComments(); assertEquals(comments.length, 2); assertInstanceOf(comments[0], Comment); assertInstanceOf(comments[1], Comment); assertEquals(comments[0].text, "hello world 1"); assertEquals(comments[1].text, "hello world 2"); });