json-as 0.8.6 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/nodejs.yml +7 -1
- package/CHANGELOG +4 -1
- package/README.md +26 -16
- package/assembly/__tests__/deserialize.spec.ts +298 -0
- package/assembly/__tests__/serialize.spec.ts +375 -0
- package/assembly/deserialize/array/array.ts +31 -0
- package/assembly/deserialize/array/bool.ts +19 -0
- package/assembly/deserialize/array/float.ts +24 -0
- package/assembly/deserialize/array/integer.ts +24 -0
- package/assembly/deserialize/array/map.ts +27 -0
- package/assembly/deserialize/array/object.ts +27 -0
- package/assembly/deserialize/array/string.ts +29 -0
- package/assembly/deserialize/array.ts +37 -0
- package/assembly/deserialize/bool.ts +18 -0
- package/assembly/deserialize/box.ts +17 -0
- package/assembly/deserialize/date.ts +11 -0
- package/assembly/deserialize/float.ts +9 -0
- package/assembly/deserialize/integer.ts +7 -0
- package/assembly/deserialize/map.ts +182 -0
- package/assembly/deserialize/object.ts +136 -0
- package/assembly/deserialize/string.ts +88 -0
- package/assembly/index.d.ts +7 -1
- package/assembly/index.ts +129 -1
- package/assembly/serialize/array.ts +52 -0
- package/assembly/serialize/bool.ts +4 -0
- package/assembly/serialize/box.ts +10 -0
- package/assembly/serialize/date.ts +4 -0
- package/assembly/serialize/float.ts +4 -0
- package/assembly/serialize/integer.ts +5 -0
- package/assembly/serialize/map.ts +24 -0
- package/assembly/serialize/object.ts +7 -0
- package/assembly/serialize/string.ts +64 -0
- package/assembly/src/sink.ts +286 -0
- package/assembly/src/util.ts +6 -0
- package/assembly/test.ts +34 -16
- package/bench/benchmark.ts +7 -3
- package/bench.js +14 -3
- package/index.ts +1 -1
- package/package.json +6 -8
- package/transform/lib/index.js +301 -183
- package/transform/lib/index.old.js +257 -0
- package/transform/lib/types.js +17 -0
- package/transform/package.json +1 -1
- package/transform/src/index.old.ts +312 -0
- package/transform/src/index.ts +301 -215
- package/transform/tsconfig.json +2 -2
- package/tsconfig.json +94 -102
- package/assembly/__benches__/as-json.ts +0 -88
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/__tests__/as-json.spec.ts +0 -673
- package/assembly/__tests__/as-pect.d.ts +0 -1
- package/assembly/src/json.ts +0 -941
|
@@ -1,673 +0,0 @@
|
|
|
1
|
-
import { JSON } from "..";
|
|
2
|
-
function canSerde<T>(data: T, toBe: string = ""): void {
|
|
3
|
-
if (!toBe) toBe = JSON.stringify<T>(data);
|
|
4
|
-
const deserialized = JSON.stringify<T>(JSON.parse<T>(JSON.stringify(data)));
|
|
5
|
-
expect(deserialized).toBe(toBe);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function canDeser<T>(data: string, toBe: T): void {
|
|
9
|
-
const deserialized = JSON.parse<T>(data);
|
|
10
|
-
expect(deserialized).toStrictEqual(toBe);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function canSer<T>(data: T, toBe: string): void {
|
|
14
|
-
const serialized = JSON.stringify<T>(data);
|
|
15
|
-
expect(serialized).toBe(toBe);
|
|
16
|
-
}
|
|
17
|
-
@json
|
|
18
|
-
class BaseObject {
|
|
19
|
-
a: string;
|
|
20
|
-
|
|
21
|
-
constructor(a: string) {
|
|
22
|
-
this.a = a;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
@json
|
|
27
|
-
class DerivedObject extends BaseObject {
|
|
28
|
-
b: string;
|
|
29
|
-
|
|
30
|
-
constructor(a: string, b: string) {
|
|
31
|
-
super(a);
|
|
32
|
-
this.b = b;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
describe("Ser/de object hierarchies", () => {
|
|
37
|
-
it("should ser/de objects derived from base objects", () => {
|
|
38
|
-
const o = new DerivedObject("1", "2");
|
|
39
|
-
const s = '{"a":"1","b":"2"}';
|
|
40
|
-
canSerde(o, s);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
@json
|
|
44
|
-
class Map4 {
|
|
45
|
-
a: string;
|
|
46
|
-
b: string;
|
|
47
|
-
c: string;
|
|
48
|
-
d: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@json
|
|
52
|
-
class Vec3 {
|
|
53
|
-
x: f64;
|
|
54
|
-
y: f64;
|
|
55
|
-
z: f64;
|
|
56
|
-
|
|
57
|
-
static shouldIgnore: string = "should not be serialized";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@json
|
|
61
|
-
class Player {
|
|
62
|
-
firstName: string;
|
|
63
|
-
lastName: string;
|
|
64
|
-
lastActive: i32[];
|
|
65
|
-
age: i32;
|
|
66
|
-
pos: Vec3 | null;
|
|
67
|
-
isVerified: boolean;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
class Nullable { }
|
|
71
|
-
type Null = Nullable | null;
|
|
72
|
-
|
|
73
|
-
describe("Ser/de Nulls", () => {
|
|
74
|
-
canSerde<Null>(null);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("Ser/de Strings", () => {
|
|
78
|
-
it("should ser/de strings", () => {
|
|
79
|
-
canSerde<string>("abcdefg");
|
|
80
|
-
canSerde<string>('st"ring" w""ith quotes"');
|
|
81
|
-
canSerde<string>('string \"with random spa\nces and \nnewlines\n\n\n');
|
|
82
|
-
canSerde<string>(
|
|
83
|
-
'string with colon : comma , brace [ ] bracket { } and quote " and other quote \\"'
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe("Ser/de Numbers", () => {
|
|
89
|
-
it("should ser/de integers", () => {
|
|
90
|
-
canSerde<i32>(0);
|
|
91
|
-
|
|
92
|
-
canSerde<u32>(100, "100");
|
|
93
|
-
canSerde<u64>(101, "101");
|
|
94
|
-
canSerde<i32>(-100, "-100");
|
|
95
|
-
canSerde<i64>(-101, "-101");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("should ser/de floats", () => {
|
|
99
|
-
canSerde<f64>(7.23, "7.23");
|
|
100
|
-
canSerde<f64>(10e2, "1000.0");
|
|
101
|
-
|
|
102
|
-
canSerde<f64>(123456e-5, "1.23456");
|
|
103
|
-
canSerde<f64>(0.0, "0.0");
|
|
104
|
-
canSerde<f64>(-7.23, "-7.23");
|
|
105
|
-
|
|
106
|
-
canSerde<f64>(1e-6, "0.000001");
|
|
107
|
-
canSerde<f64>(1e-7, "1e-7");
|
|
108
|
-
canDeser<f64>("1E-7", 1e-7);
|
|
109
|
-
|
|
110
|
-
canSerde<f64>(1e20, "100000000000000000000.0");
|
|
111
|
-
canSerde<f64>(1e21, "1e+21");
|
|
112
|
-
canDeser<f64>("1E+21", 1e21);
|
|
113
|
-
canDeser<f64>("1e21", 1e21);
|
|
114
|
-
canDeser<f64>("1E21", 1e21);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("should ser/de booleans", () => {
|
|
118
|
-
canSerde<bool>(true);
|
|
119
|
-
canSerde<bool>(false);
|
|
120
|
-
canSerde<boolean>(true);
|
|
121
|
-
canSerde<boolean>(false);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe("Ser/de Array", () => {
|
|
126
|
-
it("should ser/de integer arrays", () => {
|
|
127
|
-
canSerde<u32[]>([0, 100, 101]);
|
|
128
|
-
canSerde<u64[]>([0, 100, 101]);
|
|
129
|
-
|
|
130
|
-
canSerde<i32[]>([0, 100, 101, -100, -101]);
|
|
131
|
-
canSerde<i64[]>([0, 100, 101, -100, -101]);
|
|
132
|
-
canDeser<i32[]>(`[
|
|
133
|
-
1,
|
|
134
|
-
2,
|
|
135
|
-
3
|
|
136
|
-
]`, [1,2,3]);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it("should ser/de float arrays", () => {
|
|
140
|
-
canSerde<f64[]>([7.23, 10e2, 10e2, 123456e-5, 123456e-5, 0.0, 7.23]);
|
|
141
|
-
|
|
142
|
-
canSerde<f64[]>([1e21,1e22,1e-7,1e-8,1e-9], "[1e+21,1e+22,1e-7,1e-8,1e-9]");
|
|
143
|
-
canDeser<f64[]>("[1E+21,1E+22,1E-7,1E-8,1E-9]", [1e21,1e22,1e-7,1e-8,1e-9]);
|
|
144
|
-
canDeser<f64[]>("[1e21,1e22,1e-7,1e-8,1e-9]", [1e21,1e22,1e-7,1e-8,1e-9]);
|
|
145
|
-
canDeser<f64[]>("[1E21,1E22,1E-7,1E-8,1E-9]", [1e21,1e22,1e-7,1e-8,1e-9]);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("should ser/de boolean arrays", () => {
|
|
149
|
-
canSerde<bool[]>([true, false]);
|
|
150
|
-
canSerde<boolean[]>([true, false]);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("should ser/de string arrays", () => {
|
|
154
|
-
canSerde<string[]>(['string \"with random spa\nces and \nnewlines\n\n\n'], '["string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"]');
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("should ser/de nested integer arrays", () => {
|
|
158
|
-
canSerde<i64[][]>([[100, 101], [-100, -101], [0]]);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("should ser/de float arrays", () => {
|
|
162
|
-
canSerde<f64[][]>([
|
|
163
|
-
[7.23],
|
|
164
|
-
[10e2],
|
|
165
|
-
[10e2],
|
|
166
|
-
[123456e-5],
|
|
167
|
-
[123456e-5],
|
|
168
|
-
[0.0],
|
|
169
|
-
[7.23],
|
|
170
|
-
]);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it("should ser/de boolean arrays", () => {
|
|
174
|
-
canSerde<bool[][]>([[true], [false]]);
|
|
175
|
-
canSerde<boolean[][]>([[true], [false]]);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("should ser/de object arrays", () => {
|
|
179
|
-
canSerde<Vec3[]>([
|
|
180
|
-
{
|
|
181
|
-
x: 3.4,
|
|
182
|
-
y: 1.2,
|
|
183
|
-
z: 8.3,
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
x: 3.4,
|
|
187
|
-
y: -2.1,
|
|
188
|
-
z: 9.3,
|
|
189
|
-
},
|
|
190
|
-
]);
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
describe("Ser/de Objects", () => {
|
|
195
|
-
it("should ser/de Vec3 Objects", () => {
|
|
196
|
-
canSerde<Vec3>({
|
|
197
|
-
x: 3.4,
|
|
198
|
-
y: 1.2,
|
|
199
|
-
z: 8.3,
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
it("should ser/de deep objects", () => {
|
|
203
|
-
canSerde<Player>({
|
|
204
|
-
firstName: "Emmet",
|
|
205
|
-
lastName: "West",
|
|
206
|
-
lastActive: [8, 27, 2022],
|
|
207
|
-
age: 23,
|
|
208
|
-
pos: {
|
|
209
|
-
x: 3.4,
|
|
210
|
-
y: 1.2,
|
|
211
|
-
z: 8.3,
|
|
212
|
-
},
|
|
213
|
-
isVerified: true,
|
|
214
|
-
}, '{"firstName":"Emmet","lastName":"West","lastActive":[8,27,2022],"age":23,"pos":{"x":3.4,"y":1.2,"z":8.3},"isVerified":true}');
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it("should ser/de object with floats", () => {
|
|
218
|
-
canSerde<ObjectWithFloat>({ f: 7.23 }, '{"f":7.23}');
|
|
219
|
-
canSerde<ObjectWithFloat>({ f: 0.000001 }, '{"f":0.000001}');
|
|
220
|
-
|
|
221
|
-
canSerde<ObjectWithFloat>({ f: 1e-7 }, '{"f":1e-7}');
|
|
222
|
-
canDeser<ObjectWithFloat>('{"f":1E-7}', { f: 1e-7 });
|
|
223
|
-
|
|
224
|
-
canSerde<ObjectWithFloat>({ f: 1e20 }, '{"f":100000000000000000000.0}');
|
|
225
|
-
canSerde<ObjectWithFloat>({ f: 1e21 }, '{"f":1e+21}');
|
|
226
|
-
canDeser<ObjectWithFloat>('{"f":1E+21}', { f: 1e21 });
|
|
227
|
-
canDeser<ObjectWithFloat>('{"f":1e21}', { f: 1e21 });
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("should ser/de object with float arrays", () => {
|
|
231
|
-
canSerde<ObjectWithFloatArray>(
|
|
232
|
-
{ fa: [1e21,1e22,1e-7,1e-8,1e-9] },
|
|
233
|
-
'{"fa":[1e+21,1e+22,1e-7,1e-8,1e-9]}');
|
|
234
|
-
|
|
235
|
-
canDeser<ObjectWithFloatArray>(
|
|
236
|
-
'{"fa":[1E+21,1E+22,1E-7,1E-8,1E-9]}',
|
|
237
|
-
{ fa: [1e21,1e22,1e-7,1e-8,1e-9] });
|
|
238
|
-
|
|
239
|
-
canDeser<ObjectWithFloatArray>(
|
|
240
|
-
'{"fa":[1e21,1e22,1e-7,1e-8,1e-9]}',
|
|
241
|
-
{ fa: [1e21,1e22,1e-7,1e-8,1e-9] });
|
|
242
|
-
|
|
243
|
-
canDeser<ObjectWithFloatArray>(
|
|
244
|
-
'{"fa":[1E21,1E22,1E-7,1E-8,1E-9]}',
|
|
245
|
-
{ fa: [1e21,1e22,1e-7,1e-8,1e-9] });
|
|
246
|
-
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
describe("Ser externals", () => {
|
|
251
|
-
it("should serialize valid objects", () => {
|
|
252
|
-
canSer<Map4>({ a: '\\', b: '}', c: '][', d: '"' }, '{"a":"\\\\","b":"}","c":"][","d":"\\""}')
|
|
253
|
-
canSer<Vec3>({ x: 0.4, y: 1.4, z: 0 }, '{"x":0.4,"y":1.4,"z":0.0}')
|
|
254
|
-
})
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
@json
|
|
258
|
-
class HttpResp {
|
|
259
|
-
statusCode: number;
|
|
260
|
-
headers: Array<Array<string>>;
|
|
261
|
-
body: string;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
describe("Deser externals", () => {
|
|
265
|
-
it("should deserialize valid JSON strings", () => {
|
|
266
|
-
canDeser<Map4>('{"a":\r"\\\\",\n\r"b":"}","c":"][","d"\t:\t"\\""}', { a: '\\', b: '}', c: '][', d: '"' })
|
|
267
|
-
canDeser<Vec3>('{"x":0.4,"y":1.4,"z":0.0}', { x: 0.4, y: 1.4, z: 0 })
|
|
268
|
-
canDeser<HttpResp>('{"statusCode":200,"headers":[["Conn\\\\ection","close"],["Content-Length","375"],["ETag","W/\\"177-/Ihew5Z+fiI8NLbTM2Wyphl/PFY\\""]],\n"body":"{\\n \\\"args\\\": {},\\n \\\"headers\\\": {\\n \\\"content-length\\\": \\\"0\\\",\\n \\\"accept\\\": \\\"*/*\\\" \\n}}"}',
|
|
269
|
-
{
|
|
270
|
-
statusCode: 200,
|
|
271
|
-
headers: [
|
|
272
|
-
['Conn\\ection', 'close'],
|
|
273
|
-
['Content-Length', '375'],
|
|
274
|
-
['ETag', 'W/\"177-/Ihew5Z+fiI8NLbTM2Wyphl/PFY\"']
|
|
275
|
-
],
|
|
276
|
-
body: '{\n "args": {},\n "headers": {\n "content-length": "0",\n "accept": "*/*" \n}}'
|
|
277
|
-
})
|
|
278
|
-
})
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe("Ser/de Maps", () => {
|
|
282
|
-
it("should serialize Map<string, string>", () => {
|
|
283
|
-
const m = new Map<string, string>();
|
|
284
|
-
m.set("a", "x");
|
|
285
|
-
m.set("b", "y");
|
|
286
|
-
m.set("c", "z");
|
|
287
|
-
canSer(m, '{"a":"x","b":"y","c":"z"}');
|
|
288
|
-
});
|
|
289
|
-
it("should serialize Map<string, string | null>", () => {
|
|
290
|
-
const m = new Map<string, string | null>();
|
|
291
|
-
m.set("a", "x");
|
|
292
|
-
m.set("b", "y");
|
|
293
|
-
m.set("c", null);
|
|
294
|
-
canSer(m, '{"a":"x","b":"y","c":null}');
|
|
295
|
-
});
|
|
296
|
-
it("should serialize Map<string, string[]]>", () => {
|
|
297
|
-
const m = new Map<string, string[]>();
|
|
298
|
-
m.set("a", ["a1", "a2", "a3"]);
|
|
299
|
-
m.set("b", ["b1", "b2", "b3"]);
|
|
300
|
-
m.set("c", ["c1", "c2", "c3"]);
|
|
301
|
-
canSer(m, '{"a":["a1","a2","a3"],"b":["b1","b2","b3"],"c":["c1","c2","c3"]}');
|
|
302
|
-
});
|
|
303
|
-
it("should serialize Map<string, u32>", () => {
|
|
304
|
-
const m = new Map<string, u32>();
|
|
305
|
-
m.set("a", 1);
|
|
306
|
-
m.set("b", 2);
|
|
307
|
-
m.set("c", 3);
|
|
308
|
-
canSer(m, '{"a":1,"b":2,"c":3}');
|
|
309
|
-
});
|
|
310
|
-
it("should serialize Map<string, bool>", () => {
|
|
311
|
-
const m = new Map<string, bool>();
|
|
312
|
-
m.set("a", true);
|
|
313
|
-
m.set("b", false);
|
|
314
|
-
m.set("c", true);
|
|
315
|
-
canSer(m, '{"a":true,"b":false,"c":true}');
|
|
316
|
-
});
|
|
317
|
-
it("should serialize Map<string, Vec3>", () => {
|
|
318
|
-
const m = new Map<string, Vec3>();
|
|
319
|
-
m.set("foo", { x: 1, y: 2, z: 3 });
|
|
320
|
-
m.set("bar", { x: 11.5, y: 12.5, z: 13.5 });
|
|
321
|
-
canSer(m, '{"foo":{"x":1.0,"y":2.0,"z":3.0},"bar":{"x":11.5,"y":12.5,"z":13.5}}');
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it("should deserialize Map<string, string>", () => {
|
|
325
|
-
const m = new Map<string, string>();
|
|
326
|
-
m.set("a", "x");
|
|
327
|
-
m.set("b", "y");
|
|
328
|
-
m.set("c", "z");
|
|
329
|
-
canDeser('{"a":"x","b":"y","c":"z"}', m);
|
|
330
|
-
});
|
|
331
|
-
it("should deserialize Map<string, string | null>", () => {
|
|
332
|
-
const m = new Map<string, string | null>();
|
|
333
|
-
m.set("a", "x");
|
|
334
|
-
m.set("b", "y");
|
|
335
|
-
m.set("c", null);
|
|
336
|
-
canDeser('{"a":"x","b":"y","c":null}', m);
|
|
337
|
-
});
|
|
338
|
-
it("should deserialize Map<string, string[]>", () => {
|
|
339
|
-
const m = new Map<string, string[]>();
|
|
340
|
-
m.set("a", ["a1", "a2", "a3"]);
|
|
341
|
-
m.set("b", ["b1", "b2", "b3"]);
|
|
342
|
-
m.set("c", ["c1", "c2", "c3"]);
|
|
343
|
-
canDeser('{"a":["a1","a2","a3"],"b":["b1","b2","b3"],"c":["c1","c2","c3"]}', m);
|
|
344
|
-
});
|
|
345
|
-
it("should deserialize Map<string, u32>", () => {
|
|
346
|
-
const m = new Map<string, u32>();
|
|
347
|
-
m.set("a", 1);
|
|
348
|
-
m.set("b", 2);
|
|
349
|
-
m.set("c", 3);
|
|
350
|
-
canDeser('{"a":1,"b":2,"c":3}', m);
|
|
351
|
-
});
|
|
352
|
-
it("should deserialize Map<string, bool>", () => {
|
|
353
|
-
const m = new Map<string, bool>();
|
|
354
|
-
m.set("a", true);
|
|
355
|
-
m.set("b", false);
|
|
356
|
-
m.set("c", true);
|
|
357
|
-
canDeser('{"a":true,"b":false,"c":true}', m);
|
|
358
|
-
});
|
|
359
|
-
it("should deserialize Map<string, Vec3>", () => {
|
|
360
|
-
const m = new Map<string, Vec3>();
|
|
361
|
-
m.set("foo", { x: 1, y: 2, z: 3 });
|
|
362
|
-
m.set("bar", { x: 11.5, y: 12.5, z: 13.5 });
|
|
363
|
-
canDeser('{"foo":{"x":1.0,"y":2.0,"z":3.0},"bar":{"x":11.5,"y":12.5,"z":13.5}}', m);
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
it("should serialize Map<u32, bool>", () => {
|
|
367
|
-
const m = new Map<u32, bool>();
|
|
368
|
-
m.set(1, true);
|
|
369
|
-
m.set(2, false);
|
|
370
|
-
m.set(3, true);
|
|
371
|
-
canSer(m, '{"1":true,"2":false,"3":true}');
|
|
372
|
-
});
|
|
373
|
-
it("should deserialize Map<u32, bool>", () => {
|
|
374
|
-
const m = new Map<u32, bool>();
|
|
375
|
-
m.set(1, true);
|
|
376
|
-
m.set(2, false);
|
|
377
|
-
m.set(3, true);
|
|
378
|
-
canDeser('{"1":true,"2":false,"3":true}', m);
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it("should serialize Map<bool, string>", () => {
|
|
382
|
-
const m = new Map<bool, string>();
|
|
383
|
-
m.set(true, "a");
|
|
384
|
-
m.set(false, "b");
|
|
385
|
-
canSer(m, '{"true":"a","false":"b"}');
|
|
386
|
-
});
|
|
387
|
-
it("should deserialize Map<bool, string>", () => {
|
|
388
|
-
const m = new Map<bool, string>();
|
|
389
|
-
m.set(true, "a");
|
|
390
|
-
m.set(false, "b");
|
|
391
|
-
canDeser('{"true":"a","false":"b"}', m);
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
it("should serialize Map<string, string>[]", () => {
|
|
395
|
-
const m1 = new Map<string, string>();
|
|
396
|
-
m1.set("a", "u");
|
|
397
|
-
m1.set("b", "v");
|
|
398
|
-
m1.set("c", "w");
|
|
399
|
-
|
|
400
|
-
const m2 = new Map<string, string>();
|
|
401
|
-
m2.set("d", "x");
|
|
402
|
-
m2.set("e", "y");
|
|
403
|
-
m2.set("f", "z");
|
|
404
|
-
|
|
405
|
-
const a = [m1, m2];
|
|
406
|
-
canSer(a, '[{"a":"u","b":"v","c":"w"},{"d":"x","e":"y","f":"z"}]');
|
|
407
|
-
});
|
|
408
|
-
it("should deserialize Map<string, string>[]", () => {
|
|
409
|
-
const m1 = new Map<string, string>();
|
|
410
|
-
m1.set("a", "u");
|
|
411
|
-
m1.set("b", "v");
|
|
412
|
-
m1.set("c", "w");
|
|
413
|
-
|
|
414
|
-
const m2 = new Map<string, string>();
|
|
415
|
-
m2.set("d", "x");
|
|
416
|
-
m2.set("e", "y");
|
|
417
|
-
m2.set("f", "z");
|
|
418
|
-
|
|
419
|
-
const a = [m1, m2];
|
|
420
|
-
canDeser('[{"a":"u","b":"v","c":"w"},{"d":"x","e":"y","f":"z"}]', a);
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
describe("Ser/de escape sequences in strings", () => {
|
|
426
|
-
it("should encode short escape sequences", () => {
|
|
427
|
-
canSer("\\", '"\\\\"');
|
|
428
|
-
canSer('"', '"\\""');
|
|
429
|
-
canSer("\n", '"\\n"');
|
|
430
|
-
canSer("\r", '"\\r"');
|
|
431
|
-
canSer("\t", '"\\t"');
|
|
432
|
-
canSer("\b", '"\\b"');
|
|
433
|
-
canSer("\f", '"\\f"');
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
it("should decode short escape sequences", () => {
|
|
437
|
-
canDeser('"\\\\"', "\\");
|
|
438
|
-
canDeser('"\\""', '"');
|
|
439
|
-
canDeser('"\\n"', "\n");
|
|
440
|
-
canDeser('"\\r"', "\r");
|
|
441
|
-
canDeser('"\\t"', "\t");
|
|
442
|
-
canDeser('"\\b"', "\b");
|
|
443
|
-
canDeser('"\\f"', "\f");
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it("should decode escaped forward slash but not encode", () => {
|
|
447
|
-
canSer("/", '"/"');
|
|
448
|
-
canDeser('"/"', "/");
|
|
449
|
-
canDeser('"\\/"', "/"); // allowed
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// 0x00 - 0x1f, excluding characters that have short escape sequences
|
|
453
|
-
it("should encode long escape sequences", () => {
|
|
454
|
-
const singles = ["\n", "\r", "\t", "\b", "\f"];
|
|
455
|
-
for (let i = 0; i < 0x1F; i++) {
|
|
456
|
-
const c = String.fromCharCode(i);
|
|
457
|
-
if (singles.includes(c)) continue;
|
|
458
|
-
const actual = JSON.stringify(c);
|
|
459
|
-
const expected = `"\\u${i.toString(16).padStart(4, "0")}"`;
|
|
460
|
-
expect(actual).toBe(expected, `Failed to encode '\\x${i.toString(16).padStart(2, "0")}'`);
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
// \u0000 - \u001f
|
|
465
|
-
it("should decode long escape sequences (lower cased)", () => {
|
|
466
|
-
for (let i = 0; i <= 0x1f; i++) {
|
|
467
|
-
const s = `"\\u${i.toString(16).padStart(4, "0").toLowerCase()}"`;
|
|
468
|
-
const actual = JSON.parse<string>(s);
|
|
469
|
-
const expected = String.fromCharCode(i);
|
|
470
|
-
expect(actual).toBe(expected, `Failed to decode ${s}`);
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
// \u0000 - \u001F
|
|
475
|
-
it("should decode long escape sequences (upper cased)", () => {
|
|
476
|
-
for (let i = 0; i <= 0x1f; i++) {
|
|
477
|
-
const s = `"\\u${i.toString(16).padStart(4, "0").toUpperCase()}"`;
|
|
478
|
-
const actual = JSON.parse<string>(s);
|
|
479
|
-
const expected = String.fromCharCode(i);
|
|
480
|
-
expect(actual).toBe(expected, `Failed to decode ${s}`);
|
|
481
|
-
}
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
// See https://datatracker.ietf.org/doc/html/rfc8259#section-7
|
|
485
|
-
it("should decode UTF-16 surrogate pairs", () => {
|
|
486
|
-
const s = '"\\uD834\\uDD1E"';
|
|
487
|
-
const actual = JSON.parse<string>(s);
|
|
488
|
-
const expected = "𝄞";
|
|
489
|
-
expect(actual).toBe(expected);
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
// Just because we can decode UTF-16 surrogate pairs, doesn't mean we should encode them.
|
|
493
|
-
it("should not encode UTF-16 surrogate pairs", () => {
|
|
494
|
-
const s = "𝄞";
|
|
495
|
-
const actual = JSON.stringify(s);
|
|
496
|
-
const expected = '"𝄞"';
|
|
497
|
-
expect(actual).toBe(expected);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it("should encode multiple escape sequences", () => {
|
|
501
|
-
canSer('"""', '"\\"\\"\\""');
|
|
502
|
-
canSer('\\\\\\', '"\\\\\\\\\\\\"');
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
it("cannot parse invalid escape sequences", () => {
|
|
506
|
-
expect(() => {
|
|
507
|
-
JSON.parse<string>('"\\z"');
|
|
508
|
-
}).toThrow();
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
describe("Ser/de special strings in object values", () => {
|
|
514
|
-
it("should serialize quotes in string in object", () => {
|
|
515
|
-
const o: ObjWithString = { s: '"""' };
|
|
516
|
-
const s = '{"s":"\\"\\"\\""}';
|
|
517
|
-
canSer(o, s);
|
|
518
|
-
});
|
|
519
|
-
it("should deserialize quotes in string in object", () => {
|
|
520
|
-
const o: ObjWithString = { s: '"""' };
|
|
521
|
-
const s = '{"s":"\\"\\"\\""}';
|
|
522
|
-
canDeser(s, o);
|
|
523
|
-
});
|
|
524
|
-
it("should serialize backslashes in string in object", () => {
|
|
525
|
-
const o: ObjWithString = { s: "\\\\\\" };
|
|
526
|
-
const s = '{"s":"\\\\\\\\\\\\"}';
|
|
527
|
-
canSer(o, s);
|
|
528
|
-
});
|
|
529
|
-
it("should deserialize backslashes in string in object", () => {
|
|
530
|
-
const o: ObjWithString = { s: "\\\\\\" };
|
|
531
|
-
const s = '{"s":"\\\\\\\\\\\\"}';
|
|
532
|
-
canDeser(s, o);
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
it("should deserialize slashes in string in object", () => {
|
|
536
|
-
const o: ObjWithString = { s: "//" };
|
|
537
|
-
const s = '{"s":"/\\/"}';
|
|
538
|
-
canDeser(s, o);
|
|
539
|
-
});
|
|
540
|
-
it("should deserialize slashes in string in array", () => {
|
|
541
|
-
const a = ["/", "/"];
|
|
542
|
-
const s = '["/","\/"]';
|
|
543
|
-
canDeser(s, a);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
it("should ser/de short escape sequences in strings in objects", () => {
|
|
547
|
-
const o: ObjWithString = { s: "\n\r\t\b\f" };
|
|
548
|
-
const s = '{"s":"\\n\\r\\t\\b\\f"}';
|
|
549
|
-
canSerde(o, s);
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
it("should ser/de short escape sequences in string arrays", () => {
|
|
553
|
-
const a = ["\n", "\r", "\t", "\b", "\f"];
|
|
554
|
-
const s = '["\\n","\\r","\\t","\\b","\\f"]';
|
|
555
|
-
canSerde(a, s);
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
it("should ser/de short escape sequences in string arrays in objects", () => {
|
|
559
|
-
const o: ObjectWithStringArray = { sa: ["\n", "\r", "\t", "\b", "\f"] };
|
|
560
|
-
const s = '{"sa":["\\n","\\r","\\t","\\b","\\f"]}';
|
|
561
|
-
canSerde(o, s);
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
it("should ser/de long escape sequences in strings in objects", () => {
|
|
565
|
-
const singles = ["\n", "\r", "\t", "\b", "\f"];
|
|
566
|
-
let x = "";
|
|
567
|
-
let y = "";
|
|
568
|
-
for (let i = 0; i < 0x1F; i++) {
|
|
569
|
-
const c = String.fromCharCode(i);
|
|
570
|
-
if (singles.includes(c)) continue;
|
|
571
|
-
x += c;
|
|
572
|
-
y += `\\u${i.toString(16).padStart(4, "0")}`;
|
|
573
|
-
}
|
|
574
|
-
const o: ObjWithString = { s: x };
|
|
575
|
-
const s = `{"s":"${y}"}`;
|
|
576
|
-
canSerde(o, s);
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it("should ser/de long escape sequences in strings in arrays", () => {
|
|
580
|
-
const singles = ["\n", "\r", "\t", "\b", "\f"];
|
|
581
|
-
let x: string[] = [];
|
|
582
|
-
let y: string[] = [];
|
|
583
|
-
for (let i = 0; i < 0x1F; i++) {
|
|
584
|
-
const c = String.fromCharCode(i);
|
|
585
|
-
if (singles.includes(c)) continue;
|
|
586
|
-
x.push(c);
|
|
587
|
-
y.push(`\\u${i.toString(16).padStart(4, "0")}`);
|
|
588
|
-
}
|
|
589
|
-
const a = x;
|
|
590
|
-
const s = `["${y.join('","')}"]`;
|
|
591
|
-
canSerde(a, s);
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
it("should ser/de long escape sequences in string arrays in objects", () => {
|
|
595
|
-
const singles = ["\n", "\r", "\t", "\b", "\f"];
|
|
596
|
-
let x: string[] = [];
|
|
597
|
-
let y: string[] = [];
|
|
598
|
-
for (let i = 0; i < 0x1F; i++) {
|
|
599
|
-
const c = String.fromCharCode(i);
|
|
600
|
-
if (singles.includes(c)) continue;
|
|
601
|
-
x.push(c);
|
|
602
|
-
y.push(`\\u${i.toString(16).padStart(4, "0")}`);
|
|
603
|
-
}
|
|
604
|
-
const o: ObjectWithStringArray = { sa: x };
|
|
605
|
-
const s = `{"sa":["${y.join('","')}"]}`;
|
|
606
|
-
canSerde(o, s);
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
describe("Ser/de special strings in object keys", () => {
|
|
612
|
-
|
|
613
|
-
it("should ser/de escape sequences in key of object with int value", () => {
|
|
614
|
-
const o: ObjWithStrangeKey<i32> = { data: 123 };
|
|
615
|
-
const s = '{"a\\\\\\t\\"\\u0002b`c":123}';
|
|
616
|
-
canSerde(o, s);
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
it("should ser/de escape sequences in key of object with float value", () => {
|
|
620
|
-
const o: ObjWithStrangeKey<f64> = { data: 123.4 };
|
|
621
|
-
const s = '{"a\\\\\\t\\"\\u0002b`c":123.4}';
|
|
622
|
-
canSerde(o, s);
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
it("should ser/de escape sequences in key of object with string value", () => {
|
|
626
|
-
const o: ObjWithStrangeKey<string> = { data: "abc" };
|
|
627
|
-
const s = '{"a\\\\\\t\\"\\u0002b`c":"abc"}';
|
|
628
|
-
canSerde(o, s);
|
|
629
|
-
});
|
|
630
|
-
|
|
631
|
-
// Something buggy in as-pect needs a dummy value reflected here
|
|
632
|
-
// or the subsequent test fails. It's not used in any test.
|
|
633
|
-
Reflect.toReflectedValue(0);
|
|
634
|
-
|
|
635
|
-
it("should ser/de escape sequences in map key", () => {
|
|
636
|
-
const m = new Map<string, string>();
|
|
637
|
-
m.set('a\\\t"\x02b', 'abc');
|
|
638
|
-
const s = '{"a\\\\\\t\\"\\u0002b":"abc"}';
|
|
639
|
-
canSerde(m, s);
|
|
640
|
-
});
|
|
641
|
-
it("should ser/de escape sequences in map value", () => {
|
|
642
|
-
const m = new Map<string, string>();
|
|
643
|
-
m.set('abc', 'a\\\t"\x02b');
|
|
644
|
-
const s = '{"abc":"a\\\\\\t\\"\\u0002b"}';
|
|
645
|
-
canSerde(m, s);
|
|
646
|
-
});
|
|
647
|
-
});
|
|
648
|
-
|
|
649
|
-
@json
|
|
650
|
-
class ObjWithString {
|
|
651
|
-
s!: string;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
@json
|
|
655
|
-
class ObjectWithStringArray {
|
|
656
|
-
sa!: string[];
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
@json
|
|
660
|
-
class ObjectWithFloat {
|
|
661
|
-
f!: f64;
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
@json
|
|
665
|
-
class ObjectWithFloatArray {
|
|
666
|
-
fa!: f64[];
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
@json
|
|
670
|
-
class ObjWithStrangeKey<T> {
|
|
671
|
-
@alias('a\\\t"\x02b`c')
|
|
672
|
-
data!: T;
|
|
673
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="@as-pect/assembly/types/as-pect" />
|