json-as 1.0.0-beta.9 → 1.0.0

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.
Files changed (39) hide show
  1. package/{CHANGELOG → CHANGELOG.md} +41 -0
  2. package/README.md +102 -96
  3. package/assembly/__tests__/array.spec.ts +42 -0
  4. package/assembly/__tests__/float.spec.ts +3 -3
  5. package/assembly/__tests__/map.spec.ts +7 -0
  6. package/assembly/__tests__/raw.spec.ts +4 -5
  7. package/assembly/__tests__/struct.spec.ts +2 -2
  8. package/assembly/deserialize/simple/arbitrary.ts +8 -4
  9. package/assembly/deserialize/simple/array/arbitrary.ts +6 -6
  10. package/assembly/deserialize/simple/array/array.ts +4 -3
  11. package/assembly/deserialize/simple/array/bool.ts +7 -7
  12. package/assembly/deserialize/simple/array/float.ts +2 -2
  13. package/assembly/deserialize/simple/array/integer.ts +1 -1
  14. package/assembly/deserialize/simple/array/map.ts +1 -1
  15. package/assembly/deserialize/simple/array/string.ts +3 -3
  16. package/assembly/deserialize/simple/array/struct.ts +14 -3
  17. package/assembly/deserialize/simple/array.ts +3 -0
  18. package/assembly/deserialize/simple/map.ts +93 -75
  19. package/assembly/deserialize/simple/object.ts +26 -16
  20. package/assembly/deserialize/simple/struct.ts +31 -19
  21. package/assembly/index.ts +14 -11
  22. package/assembly/serialize/simple/array.ts +1 -0
  23. package/assembly/serialize/simple/bool.ts +1 -0
  24. package/assembly/serialize/simple/date.ts +1 -0
  25. package/assembly/serialize/simple/float.ts +1 -0
  26. package/assembly/serialize/simple/integer.ts +1 -0
  27. package/assembly/serialize/simple/map.ts +1 -0
  28. package/assembly/serialize/simple/object.ts +1 -0
  29. package/assembly/serialize/simple/raw.ts +1 -0
  30. package/assembly/serialize/simple/string.ts +1 -0
  31. package/assembly/test.ts +18 -0
  32. package/index.ts +1 -1
  33. package/package.json +4 -3
  34. package/run-tests.sh +1 -1
  35. package/transform/lib/index.js +29 -69
  36. package/transform/lib/index.js.map +1 -1
  37. package/transform/src/index.ts +55 -71
  38. package/.gitmodules +0 -0
  39. package/assembly/as-bs.d.ts +0 -53
@@ -1,5 +1,46 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-03-09 - 1.0.0
4
+
5
+ - fix: relative paths pointing through node_modules would create a second Source
6
+ - feat: move behavior of `--lib` into transform itself
7
+ - fix: object with an object as a value containing a rhs bracket or brace would exit early [3b33e94](https://github.com/JairusSW/json-as/commit/3b33e9414dc04779d22d65272863372fcd7af4a6)
8
+
9
+ ## 2025-03-04 - 1.0.0-beta.17
10
+
11
+ - fix: forgot to build transform
12
+
13
+ ## 2025-03-04 - 1.0.0-beta.16
14
+
15
+ - fix: isPrimitive should only trigger on actual primitives
16
+
17
+ ## 2025-03-04 - 1.0.0-beta.15
18
+
19
+ - fix: deserialize custom should take in string
20
+
21
+ ## 2025-03-04 - 1.0.0-beta.14
22
+
23
+ - fix: reference to nonexistent variable during custom deserialization layer 2
24
+
25
+ ## 2025-03-04 - 1.0.0-beta.13
26
+
27
+ - fix: forgot to actually build the transform
28
+
29
+ ## 2025-03-04 - 1.0.0-beta.12
30
+
31
+ - fix: build transform
32
+
33
+ ## 2025-03-04 - 1.0.0-beta.11
34
+
35
+ - fix: wrongly assumed pointer types within arbitrary deserialization
36
+ - fix: wrong pointer type being passed during map deserialization
37
+
38
+ ## 2025-03-04 - 1.0.0-beta.10
39
+
40
+ - fix: transform not generating the right load operations for keys
41
+ - fix: whitespace not working in objects or struct deserialization
42
+ - fix: JSON.Raw not working when deserializing as Map<string, JSON.Raw>
43
+
3
44
  ## 2025-03-03 - 1.0.0-beta.9
4
45
 
5
46
  - rename: change libs folder to lib
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.0.0-beta.9
9
+ AssemblyScript - v1.0.0
10
10
  </pre>
11
11
  </h5>
12
12
 
@@ -14,6 +14,20 @@
14
14
 
15
15
  JSON is the de-facto serialization format of modern web applications, but its serialization and deserialization remain a significant performance bottleneck, especially at scale. Traditional parsing approaches are computationally expensive, adding unnecessary overhead to both clients and servers. This library is designed to mitigate this by leveraging SIMD acceleration and highly optimized transformations.
16
16
 
17
+ ## 🚨 What's new in v1.0.0
18
+
19
+ 🔹Breaking changes to the way custom serializers/deserializers function (See Custom Serializers below)
20
+
21
+ 🔹Major performance improvements and addition of SIMD
22
+
23
+ 🔹Extremely low memory overhead compared to pre-1.x.x versions (great for serverless workloads)
24
+
25
+ 🔹Fixes to many major issues and newly discovered bugs
26
+
27
+ 🔹Full support for dynamic objects, arrays, and values
28
+
29
+ 🔹Full support for `JSON.Raw` type everywhere
30
+
17
31
  ## 📚 Contents
18
32
 
19
33
  - [Installation](#-installation)
@@ -31,22 +45,21 @@ JSON is the de-facto serialization format of modern web applications, but its se
31
45
  ## 💾 Installation
32
46
 
33
47
  ```bash
34
- npm install json-as@1.0.0-beta.9
48
+ npm install json-as
35
49
  ```
36
50
 
37
51
  Add the `--transform` to your `asc` command (e.g. in package.json)
38
52
 
39
53
  ```bash
40
- --transform json-as/transform --lib json-as/lib
54
+ --transform json-as/transform
41
55
  ```
42
56
 
43
57
  Alternatively, add it to your `asconfig.json`
44
58
 
45
- ```json
59
+ ```typescript
46
60
  {
47
61
  "options": {
48
- "transform": ["json-as/transform"],
49
- "lib": ["json-as/lib"]
62
+ "transform": ["json-as/transform"]
50
63
  }
51
64
  }
52
65
  ```
@@ -55,7 +68,7 @@ If you'd like to see the code that the transform generates, run with `JSON_DEBUG
55
68
 
56
69
  ## 🪄 Usage
57
70
 
58
- ```js
71
+ ```typescript
59
72
  import { JSON } from "json-as";
60
73
 
61
74
  @json
@@ -82,15 +95,15 @@ class Player {
82
95
  const player: Player = {
83
96
  firstName: "Jairus",
84
97
  lastName: "Tanaka",
85
- lastActive: [2, 13, 2025],
98
+ lastActive: [3, 9, 2025],
86
99
  age: 18,
87
100
  pos: {
88
101
  x: 3.4,
89
102
  y: 1.2,
90
- z: 8.3
103
+ z: 8.3,
91
104
  },
92
- isVerified: true
93
- };
105
+ isVerified: true,
106
+ }
94
107
 
95
108
  const serialized = JSON.stringify<Player>(player);
96
109
  const deserialized = JSON.parse<Player>(serialized);
@@ -109,26 +122,26 @@ This library allows selective omission of fields during serialization using the
109
122
 
110
123
  This decorator excludes a field from serialization entirely.
111
124
 
112
- ```js
125
+ ```typescript
113
126
  @json
114
127
  class Example {
115
128
  name!: string;
116
129
  @omit
117
- secret!: string;
130
+ SSN!: string;
118
131
  }
119
132
 
120
133
  const obj = new Example();
121
- obj.name = "Visible";
122
- obj.secret = "Hidden";
134
+ obj.name = "Jairus";
135
+ obj.SSN = "123-45-6789";
123
136
 
124
- console.log(JSON.stringify(obj)); // { "name": "Visible" }
137
+ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
125
138
  ```
126
139
 
127
140
  **@omitnull**
128
141
 
129
142
  This decorator omits a field only if its value is null.
130
143
 
131
- ```js
144
+ ```typescript
132
145
  @json
133
146
  class Example {
134
147
  name!: string;
@@ -137,30 +150,36 @@ class Example {
137
150
  }
138
151
 
139
152
  const obj = new Example();
140
- obj.name = "Present";
153
+ obj.name = "Jairus";
141
154
  obj.optionalField = null;
142
155
 
143
- console.log(JSON.stringify(obj)); // { "name": "Present" }
156
+ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
157
+ ```
144
158
 
145
- @omitif((self: this) => condition)
159
+ **@omitif((self: this) => condition)**
146
160
 
147
161
  This decorator omits a field based on a custom predicate function.
148
162
 
163
+ ```typescript
149
164
  @json
150
165
  class Example {
151
166
  name!: string;
152
- @omitif((self: Example) => self.age < 18)
167
+ @omitif((self: Example) => self.age <= 18)
153
168
  age!: number;
154
169
  }
155
170
 
156
171
  const obj = new Example();
157
- obj.name = "John";
158
- obj.age = 16;
172
+ obj.name = "Jairus";
173
+ obj.age = 18;
174
+
175
+ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
176
+
177
+ obj.age = 99;
159
178
 
160
- console.log(JSON.stringify(obj)); // { "name": "John" }
179
+ console.log(JSON.stringify(obj)); // { "name": "Jairus", "age": 99 }
161
180
  ```
162
181
 
163
- If age were 18 or higher, it would be included in the serialization.
182
+ If age were higher than 18, it would be included in the serialization.
164
183
 
165
184
  ### 🗳️ Using nullable primitives
166
185
 
@@ -168,7 +187,7 @@ AssemblyScript doesn't support using nullable primitive types, so instead, json-
168
187
 
169
188
  For example, this schema won't compile in AssemblyScript:
170
189
 
171
- ```js
190
+ ```typescript
172
191
  @json
173
192
  class Person {
174
193
  name!: string;
@@ -178,7 +197,7 @@ class Person {
178
197
 
179
198
  Instead, use `JSON.Box` to allow nullable primitives:
180
199
 
181
- ```js
200
+ ```typescript
182
201
  @json
183
202
  class Person {
184
203
  name: string;
@@ -188,11 +207,11 @@ class Person {
188
207
  }
189
208
  }
190
209
 
191
- const person = new Person("Bob");
192
- console.log(JSON.stringify(person)); // {"name":"Bob","age":null}
210
+ const person = new Person("Jairus");
211
+ console.log(JSON.stringify(person)); // {"name":"Jairus","age":null}
193
212
 
194
213
  person.age = new JSON.Box<i32>(18); // Set age to 18
195
- console.log(JSON.stringify(person)); // {"name":"Bob","age":18}
214
+ console.log(JSON.stringify(person)); // {"name":"Jairus","age":18}
196
215
  ```
197
216
 
198
217
  ### 📤 Working with unknown or dynamic data
@@ -205,31 +224,31 @@ Here's a few examples:
205
224
 
206
225
  **Working with multi-type arrays**
207
226
 
208
- When dealing with arrays that have multiple types within them, eg. `["string",true,null,["array"]]`, use `JSON.Value[]`
227
+ When dealing with arrays that have multiple types within them, eg. `["string",true,["array"]]`, use `JSON.Value[]`
209
228
 
210
- ```js
211
- const a1 = JSON.parse<JSON.Value[]>('["string",true,null,["array"]]');
229
+ ```typescript
230
+ const a = JSON.parse<JSON.Value[]>('["string",true,["array"]]');
212
231
  console.log(JSON.stringify(a[0])); // "string"
213
232
  console.log(JSON.stringify(a[1])); // true
214
- console.log(JSON.stringify(a[2])); // null
215
- console.log(JSON.stringify(a[3])); // ["array"]
233
+ console.log(JSON.stringify(a[2])); // ["array"]
216
234
  ```
217
235
 
218
236
  **Working with unknown objects**
219
237
 
220
238
  When dealing with an object with an unknown structure, use the `JSON.Obj` type
221
239
 
222
- ```js
223
- const o1 = JSON.parse<JSON.Obj>('{"a":3.14,"b":true,"c":[1,2,3],"d":{"x":1,"y":2,"z":3}}');
240
+ ```typescript
241
+ const obj = JSON.parse<JSON.Obj>('{"a":3.14,"b":true,"c":[1,2,3],"d":{"x":1,"y":2,"z":3}}');
224
242
 
225
- console.log(o1.keys().join(" ")); // a b c d
226
- console.log(
227
- o1.values()
228
- .map<string>((v) => JSON.stringify(v))
229
- .join(" ")
243
+ console.log("Keys: " + obj.keys().join(" ")); // a b c d
244
+ console.log("Values: " +
245
+ obj
246
+ .values()
247
+ .map<string>((v) => JSON.stringify(v))
248
+ .join(" "),
230
249
  ); // 3.14 true [1,2,3] {"x":1,"y":2,"z":3}
231
250
 
232
- const y = o1.get("d").get<JSON.Obj>().get<i32>();
251
+ const y = obj.get("d")!.get<JSON.Obj>().get("y")!;
233
252
  console.log('o1["d"]["y"] = ' + y.toString()); // o1["d"]["y"] = 2
234
253
  ```
235
254
 
@@ -239,7 +258,7 @@ More often, objects will be completely statically typed except for one or two va
239
258
 
240
259
  In such cases, `JSON.Value` can be used to handle fields that may hold different types at runtime.
241
260
 
242
- ```js
261
+ ```typescript
243
262
  @json
244
263
  class DynamicObj {
245
264
  id: i32 = 0;
@@ -267,24 +286,22 @@ Sometimes its necessary to simply copy a string instead of serializing it.
267
286
 
268
287
  For example, the following data would typically be serialized as:
269
288
 
270
- ```js
271
- const m1 = new Map<string, string>();
272
- m1.set('pos', '{"x":1.0,"y":2.0,"z":3.0}');
289
+ ```typescript
290
+ const map = new Map<string, string>();
291
+ map.set("pos", '{"x":1.0,"y":2.0,"z":3.0}');
273
292
 
274
- const a1 = JSON.stringify(m1);
275
- console.log("a1: " + a1);
293
+ console.log(JSON.stringify(map));
276
294
  // {"pos":"{\"x\":1.0,\"y\":2.0,\"z\":3.0}"}
277
295
  // pos's value (Vec3) is contained within a string... ideally, it should be left alone
278
296
  ```
279
297
 
280
298
  If, instead, one wanted to insert Raw JSON into an existing schema/data structure, they could make use of the JSON.Raw type to do so:
281
299
 
282
- ```js
283
- const m1 = new Map<string, JSON.Raw>();
284
- m1.set('pos', new JSON.Raw('{"x":1.0,"y":2.0,"z":3.0}'));
300
+ ```typescript
301
+ const map = new Map<string, JSON.Raw>();
302
+ map.set("pos", new JSON.Raw('{"x":1.0,"y":2.0,"z":3.0}'));
285
303
 
286
- const a1 = JSON.stringify(m1);
287
- console.log("a1: " + a1);
304
+ console.log(JSON.stringify(map));
288
305
  // {"pos":{"x":1.0,"y":2.0,"z":3.0}}
289
306
  // Now its properly formatted JSON where pos's value is of type Vec3 not string!
290
307
  ```
@@ -295,7 +312,9 @@ This library supports custom serialization and deserialization methods, which ca
295
312
 
296
313
  Here's an example of creating a custom data type called `Point` which serializes to `(x,y)`
297
314
 
298
- ```js
315
+ ```typescript
316
+ import { bytes } from "json-as/assembly/util";
317
+
299
318
  @json
300
319
  class Point {
301
320
  x: f64 = 0.0;
@@ -319,12 +338,17 @@ class Point {
319
338
  const x = data.slice(1, c);
320
339
  const y = data.slice(c + 1, data.length - 1);
321
340
 
322
- return new Point(
323
- f64.parse(x),
324
- f64.parse(y)
325
- );
341
+ return new Point(f64.parse(x), f64.parse(y));
326
342
  }
327
343
  }
344
+
345
+ const obj = new Point(3.5, -9.2);
346
+
347
+ const serialized = JSON.stringify<Point>(obj);
348
+ const deserialized = JSON.parse<Point>(serialized);
349
+
350
+ console.log("Serialized " + serialized);
351
+ console.log("Deserialized " + JSON.stringify(deserialized));
328
352
  ```
329
353
 
330
354
  The serializer function converts a `Point` instance into a string format `(x,y)`.
@@ -333,7 +357,7 @@ The deserializer function parses the string `(x,y)` back into a `Point` instance
333
357
 
334
358
  These functions are then wrapped before being consumed by the json-as library:
335
359
 
336
- ```js
360
+ ```typescript
337
361
  @inline __SERIALIZE_CUSTOM(ptr: usize): void {
338
362
  const data = this.serializer(changetype<Point>(ptr));
339
363
  const dataSize = data.length << 1;
@@ -352,45 +376,27 @@ This allows custom serialization while maintaining a generic interface for the l
352
376
 
353
377
  The `json-as` library has been optimized to achieve near-gigabyte-per-second JSON processing speeds through SIMD acceleration and highly efficient transformations. Below are some key performance benchmarks to give you an idea of how it performs.
354
378
 
355
- ### Raw Performance
356
-
357
- Simple
358
-
359
- | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
360
- | ------------------ | --------------------- | ----------------------- | -------------------- | ---------------------- |
361
- | Vector3 Object | 32,642,320 ops/s | 9,736,272 ops/s | 1,240 MB/s | 369 MB/s |
362
- | Alphabet String | 4,928,856 ops/s | 7,567,360 ops/s | 975 MB/s | 1,498 MB/s |
363
- | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
364
- | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
365
- | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
366
-
367
- SIMD
368
-
369
- | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
370
- | ------------------ | --------------------- | ----------------------- | -------------------- | ---------------------- |
371
- | Vector3 Object | 32,642,320 ops/s | 9,736,272 ops/s | 1,240 MB/s | 369 MB/s |
372
- | Alphabet String | 20,368,584 ops/s | 28,467,424 ops/s | 3,910 MB/s | 5,636 MB/s |
373
- | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
374
- | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
375
- | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
379
+ Note: the AssemblyScript benches are run using a _bump allocator_ so that Garbage Collection does not interfere with results. Also note that ideally, I would use [d8](https://v8.dev/docs/d8), but until that is done, these results serve as a temporary performance comparison.
376
380
 
377
- JavaScript
381
+ **Table 1** - _AssemblyScript_
378
382
 
379
- | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
380
- | ------------------ | --------------------- | ----------------------- | -------------------- | ---------------------- |
381
- | Vector3 Object | 2,548,013 ops/s | 1,942,440 ops/s | 97 MB/s | 73 MB/s |
382
- | Alphabet String | 3,221,556 ops/s | 2,716,617 ops/s | 624 MB/s | 537 MB/s |
383
- | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
384
- | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
385
- | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
383
+ | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
384
+ | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
385
+ | Vector3 Object | 38 bytes | 35,714,285 ops/s | 35,435,552 ops/s | 1,357 MB/s | 1,348 MB/s |
386
+ | Alphabet String | 104 bytes | 13,617,021 ops/s | 18,390,804 ops/s | 1,416 MB/s | 1,986 MB/s |
387
+ | Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
388
+ | Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
389
+ | Large Object | 3374 bytes | 614,754 ops/s | 132,802 ops/s | 2,074 MB/s | 448.0 MB/s |
386
390
 
387
- ### Real-World Usage
391
+ **Table 2** - _JavaScript_
388
392
 
389
- | Scenario | JSON Size (kb) | Serialization Time (ops/s) | Deserialization Time (ops/s) | Throughput (GB/s) |
390
- | ---------------- | -------------- | -------------------------- | ---------------------------- | ----------------- |
391
- | Web API Response | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
392
- | Database Entry | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
393
- | File Parsing | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
393
+ | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
394
+ | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
395
+ | Vector3 Object | 38 bytes | 8,791,209 ops/s | 5,369,12 ops/s | 357.4 MB/s | 204.3 MB/s |
396
+ | Alphabet String | 104 bytes | 13,793,103 ops/s | 14,746,544 ops/s | 1,416 MB/s | 1,592 MB/s |
397
+ | Small Object | 88 bytes | 8,376,963 ops/s | 4,968,944 ops/s | 737.1 MB/s | 437.2 MB/s |
398
+ | Medium Object | 494 bytes | 2,395,210 ops/s | 1,381,693 ops/s | 1,183 MB/s | 682.5 MB/s |
399
+ | Large Object | 3374 bytes | 222,222 ops/s | 117,233 ops/s | 749.7 MB/s | 395.5 MB/s |
394
400
 
395
401
  ## 📃 License
396
402
 
@@ -403,4 +409,4 @@ Please send all issues to [GitHub Issues](https://github.com/JairusSW/json-as/is
403
409
  - **Email:** Send me inquiries, questions, or requests at [me@jairus.dev](mailto:me@jairus.dev)
404
410
  - **GitHub:** Visit the official GitHub repository [Here](https://github.com/JairusSW/json-as)
405
411
  - **Website:** Visit my official website at [jairus.dev](https://jairus.dev/)
406
- - **Discord:** Contact me at [My Discord](https://discord.com/users/600700584038760448) or on the [AssemblyScript Discord Server](https://discord.gg/assemblyscript/)
412
+ - **Discord:** Contact me at [My Discord](https://discord.com/users/600700584038760448) or on the [AssemblyScript Discord Server](https://discord.gg/assemblyscript/)
@@ -58,6 +58,48 @@ describe("Should serialize object arrays", () => {
58
58
  ).toBe('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
59
59
  });
60
60
 
61
+ describe("Should deserialize integer arrays", () => {
62
+ expect(JSON.stringify(JSON.parse<u32[]>("[0,100,101]"))).toBe('[0,100,101]');
63
+ expect(JSON.stringify(JSON.parse<u64[]>("[0,100,101]"))).toBe('[0,100,101]');
64
+ expect(JSON.stringify(JSON.parse<i32[]>("[0,100,101,-100,-101]"))).toBe("[0,100,101,-100,-101]");
65
+ expect(JSON.stringify(JSON.parse<i64[]>("[0,100,101,-100,-101]"))).toBe("[0,100,101,-100,-101]");
66
+ });
67
+
68
+ describe("Should deserialize float arrays", () => {
69
+ expect(JSON.stringify(JSON.parse<f64[]>("[7.23,1000.0,1000.0,1.23456,1.23456,0.0,7.23]"))).toBe("[7.23,1000.0,1000.0,1.23456,1.23456,0.0,7.23]");
70
+ expect(JSON.stringify(JSON.parse<f64[]>("[1e+21,1e+22,1e-7,1e-8,1e-9]"))).toBe("[1e+21,1e+22,1e-7,1e-8,1e-9]");
71
+ });
72
+
73
+ describe("Should deserialize boolean arrays", () => {
74
+ expect(JSON.stringify(JSON.parse<bool[]>("[true,false]"))).toBe("[true,false]");
75
+ expect(JSON.stringify(JSON.parse<boolean[]>("[true,false]"))).toBe("[true,false]");
76
+ });
77
+
78
+ describe("Should deserialize string arrays", () => {
79
+ expect(JSON.stringify(JSON.parse<string[]>("[\"string \\\"with random spa\\nces and \\nnewlines\\n\\n\\n\"]"))).toBe("[\"string \\\"with random spa\\nces and \\nnewlines\\n\\n\\n\"]");
80
+ });
81
+
82
+ describe("Should deserialize nested integer arrays", () => {
83
+ expect(JSON.stringify(JSON.parse<i64[][]>("[[100,101],[-100,-101],[0]]"))).toBe("[[100,101],[-100,-101],[0]]");
84
+ });
85
+
86
+ describe("Should deserialize nested float arrays", () => {
87
+ expect(JSON.stringify(JSON.parse<f64[][]>("[[7.23],[1000.0],[1000.0],[1.23456],[1.23456],[0.0],[7.23]]"))).toBe("[[7.23],[1000.0],[1000.0],[1.23456],[1.23456],[0.0],[7.23]]");
88
+ });
89
+
90
+ describe("Should deserialize nested boolean arrays", () => {
91
+ expect(JSON.stringify(JSON.parse<bool[][]>("[[true],[false]]"))).toBe("[[true],[false]]");
92
+ expect(JSON.stringify(JSON.parse<boolean[][]>("[[true],[false]]"))).toBe("[[true],[false]]");
93
+ });
94
+
95
+ describe("Should deserialize object arrays", () => {
96
+ expect(
97
+ JSON.stringify(JSON.parse<Vec3[]>(
98
+ '[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]'
99
+ )
100
+ )).toBe('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
101
+ });
102
+
61
103
  @json
62
104
  class Vec3 {
63
105
  x: f64 = 0.0;
@@ -34,9 +34,9 @@ describe("Should deserialize floats", () => {
34
34
 
35
35
  expect(JSON.parse<f64>("0.000001").toString()).toBe("0.000001");
36
36
 
37
- // expect(JSON.parse<f64>("1e-7")).toBe(1e-7);
37
+ expect(JSON.parse<f64>("1e-7").toString()).toBe(1e-7.toString());
38
38
 
39
- // expect(JSON.parse<f64>("100000000000000000000.0").toString()).toBe(1e20);
39
+ expect(JSON.parse<f64>("100000000000000000000.0").toString()).toBe(1e20.toString());
40
40
 
41
- // expect(JSON.parse<f64>("1e+21")).toBe(1e21);
41
+ expect(JSON.parse<f64>("1e+21").toString()).toBe(1e21.toString());
42
42
  });
@@ -0,0 +1,7 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+
4
+ describe("Should deserialize complex objects", () => {
5
+ const input = '{"a":{"b":{"c":[{"d":"random value 1"},{"e":["value 2","value 3"]}],"f":{"g":{"h":[1,2,3],"i":{"j":"nested value"}}}},"k":"simple value"},"l":[{"m":"another value","n":{"o":"deep nested","p":[{"q":"even deeper"},"final value"]}}],"r":null}';
6
+ expect(JSON.stringify(JSON.parse<Map<string, JSON.Raw>>(input))).toBe(input);
7
+ })
@@ -17,8 +17,7 @@ describe("Should serialize Map<string, JSON.Raw>", () => {
17
17
  expect(JSON.stringify(m1)).toBe('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
18
18
  });
19
19
 
20
- // describe("Should deserialize Map<string, JSON.Raw>", () => {
21
- // const m1 = JSON.parse<Map<string, JSON.Raw>>('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
22
-
23
- // expect(JSON.stringify(m1)).toBe('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
24
- // });
20
+ describe("Should deserialize Map<string, JSON.Raw>", () => {
21
+ const m1 = JSON.parse<Map<string, JSON.Raw>>('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
22
+ expect(JSON.stringify(m1)).toBe('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
23
+ });
@@ -64,9 +64,9 @@ describe("Should deserialize structs with whitespace", () => {
64
64
  ).toBe('{"x":3.4,"y":1.2,"z":8.3}');
65
65
  });
66
66
 
67
- describe("Should serialize Suite struct", () => {
67
+ // describe("Should serialize Suite struct", () => {
68
68
 
69
- });
69
+ // });
70
70
 
71
71
  @json
72
72
  class BaseObject {
@@ -4,14 +4,18 @@ import { deserializeBoolean } from "./bool";
4
4
  import { deserializeFloat } from "./float";
5
5
  import { deserializeString } from "./string";
6
6
  import { deserializeObject } from "./object";
7
+ import { BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE } from "../../custom/chars";
7
8
 
8
9
  export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value {
9
10
  const firstChar = load<u16>(srcStart);
10
- if (firstChar == 34) return JSON.Value.from(deserializeString(srcStart, srcEnd, dst));
11
- else if (firstChar == 123) return JSON.Value.from(deserializeObject(srcStart, srcEnd, dst));
11
+ if (firstChar == QUOTE) return JSON.Value.from(deserializeString(srcStart, srcEnd, 0));
12
+ else if (firstChar == BRACE_LEFT) return JSON.Value.from(deserializeObject(srcStart, srcEnd, 0));
12
13
  else if (firstChar - 48 <= 9 || firstChar == 45) return JSON.Value.from(deserializeFloat<f64>(srcStart, srcEnd));
13
- else if (firstChar == 91) {
14
- return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, dst));
14
+ else if (firstChar == BRACKET_LEFT) {
15
+ return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, 0));
15
16
  } else if (firstChar == 116 || firstChar == 102) return JSON.Value.from(deserializeBoolean(srcStart, srcEnd));
17
+ else if (firstChar == CHAR_N) {
18
+ return JSON.Value.from(null);
19
+ }
16
20
  return unreachable();
17
21
  }
@@ -4,7 +4,7 @@ import { isSpace } from "util/string";
4
4
  import { ptrToStr } from "../../../util/ptrToStr";
5
5
 
6
6
  export function deserializeArbitraryArray(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
7
- const out = dst ? changetype<JSON.Value[]>(dst) : instantiate<JSON.Value[]>();
7
+ const out = changetype<JSON.Value[]>(dst || changetype<usize>(instantiate<JSON.Value[]>()));
8
8
  let lastIndex: usize = 0;
9
9
  let depth: u32 = 0;
10
10
  // if (load<u16>(srcStart) != BRACKET_LEFT)
@@ -121,12 +121,12 @@ export function deserializeArbitraryArray(srcStart: usize, srcEnd: usize, dst: u
121
121
  }
122
122
  } else if (code == CHAR_N) {
123
123
  if (load<u64>(srcStart) == 30399761348886638) {
124
+ console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
124
125
  // @ts-ignore: type
125
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, (srcStart += 8)));
126
- // console.log("Value (null): " + ptrToStr(srcStart - 8, srcStart));
127
- while (isSpace(load<u16>((srcStart += 2)))) {
128
- /* empty */
129
- }
126
+ out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 8)));
127
+ // while (isSpace(load<u16>((srcStart += 2)))) {
128
+ // /* empty */
129
+ // }
130
130
  }
131
131
  }
132
132
  srcStart += 2;
@@ -2,15 +2,16 @@ import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../../";
3
3
 
4
4
  export function deserializeArrayArray<T extends unknown[][]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
- const out = dst ? changetype<T>(dst) : instantiate<T>();
5
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
6
6
  let lastIndex: usize = 0;
7
7
  let depth: u32 = 0;
8
- while (srcStart < srcEnd) {
8
+ srcStart += 2;
9
+ while (srcStart < srcEnd - 2) {
9
10
  const code = load<u16>(srcStart);
10
11
  if (code == BRACKET_LEFT && depth++ == 0) {
11
12
  lastIndex = srcStart;
12
13
  } else if (code == BRACKET_RIGHT && --depth == 0) {
13
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
14
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2));
14
15
  }
15
16
  srcStart += 2;
16
17
  }
@@ -1,17 +1,17 @@
1
- import { CHAR_E, CHAR_F, CHAR_T } from "../../../custom/chars";
2
-
3
1
  export function deserializeBooleanArray<T extends boolean[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
4
- const out = dst ? changetype<T>(dst) : instantiate<T>();
2
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
3
+ srcStart += 2; // skip [
5
4
  while (srcStart < srcEnd) {
6
- const code = load<u16>(srcStart);
7
- if (code == CHAR_T && load<u16>(srcStart, 8) == CHAR_E) {
5
+ const block = load<u64>(srcStart);
6
+ if (block == 28429475166421108) {
8
7
  out.push(true);
9
8
  srcStart += 10;
10
- } else if (code == CHAR_F && load<u16>(srcStart, 10) == CHAR_E) {
9
+ } else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) {
11
10
  out.push(false);
12
11
  srcStart += 12;
12
+ } else {
13
+ srcStart += 2;
13
14
  }
14
- srcStart += 2;
15
15
  }
16
16
  return out;
17
17
  }
@@ -1,9 +1,9 @@
1
1
  import { isSpace } from "../../../util";
2
- import { COMMA, BRACE_RIGHT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
3
  import { JSON } from "../../..";
4
4
 
5
5
  export function deserializeFloatArray<T extends number[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
- const out = dst ? changetype<T>(dst) : instantiate<T>();
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
7
  let lastIndex: usize = 0;
8
8
  while (srcStart < srcEnd) {
9
9
  const code = load<u16>(srcStart);