mapconversion.ts
⎇
Raw
1//needed to convert ES6 maps from/to json
2type SerializablePrimitive = string | number | boolean | null;
3type SerializableArray = Serializable[];
4type SerializableObject = { [key: string]: Serializable };
5type Serializable = SerializablePrimitive | SerializableArray | SerializableObject | SerializedMap;
6
7interface SerializedMap {
8 __type: "Map";
9 value: [Serializable, Serializable][];
10}
11
12function isSerializedMap(value: unknown): value is SerializedMap {
13 return (
14 typeof value === "object" &&
15 value !== null &&
16 "__type" in value &&
17 (value as SerializedMap).__type === "Map" &&
18 "value" in value &&
19 Array.isArray((value as SerializedMap).value)
20 );
21}
22
23function isMap(value: unknown): value is Map<unknown, unknown> {
24 return value instanceof Map;
25}
26
27function convertMapToSerializable(map: Map<unknown, unknown>): SerializedMap {
28 const serializedEntries: [Serializable, Serializable][] = [];
29
30 map.forEach((value, key) => {
31 serializedEntries.push([convertToSerializable(key), convertToSerializable(value)]);
32 });
33
34 return {
35 __type: "Map",
36 value: serializedEntries,
37 };
38}
39
40function convertToSerializable(value: unknown): Serializable {
41 if (isMap(value)) {
42 return convertMapToSerializable(value);
43 }
44
45 if (Array.isArray(value)) {
46 return value.map((item) => convertToSerializable(item));
47 }
48
49 if (typeof value === "object" && value !== null) {
50 const result: SerializableObject = {};
51 for (const [k, v] of Object.entries(value)) {
52 result[k] = convertToSerializable(v);
53 }
54 return result;
55 }
56
57 return value as Serializable;
58}
59
60function reviveMap(data: SerializedMap): Map<unknown, unknown> {
61 return new Map(data.value.map(([key, value]) => [reviveFromSerializable(key), reviveFromSerializable(value)]));
62}
63
64function reviveFromSerializable(value: unknown): unknown {
65 if (isSerializedMap(value)) {
66 return reviveMap(value);
67 }
68
69 if (Array.isArray(value)) {
70 return value.map((item) => reviveFromSerializable(item));
71 }
72
73 if (typeof value === "object" && value !== null) {
74 const result: Record<string, unknown> = {};
75 for (const [k, v] of Object.entries(value)) {
76 result[k] = reviveFromSerializable(v);
77 }
78 return result;
79 }
80
81 return value;
82}
83
84export function stringifyMap(value: unknown): string {
85 return JSON.stringify(convertToSerializable(value));
86}
87
88export function parseMap(jsonString: string): unknown {
89 return reviveFromSerializable(JSON.parse(jsonString));
90}