json-as 1.1.14 → 1.1.15-preview.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Change Log
2
2
 
3
+ ## UNRELEASED
4
+
5
+ - feat: add `.as<T>()` method to `JSON.Value`
6
+ - chore: remove all references to `__SERIALIZE_CUSTOM`
7
+ - feat: add support for `StaticArray` serialization
8
+ - feat: support `JSON.Raw` in array types
9
+ - tests: add tests for `JSON.Raw[]`
10
+ - tests: properly support nulls (in testing lib)
11
+
3
12
  ## 2025-05-29 - 1.1.14
4
13
 
5
14
  - fix: hotfix schema resolver
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.1.14
9
+ AssemblyScript - v1.1.15-preview.2
10
10
  </pre>
11
11
  </h6>
12
12
 
@@ -23,6 +23,7 @@ JSON is the de-facto serialization format of modern web applications, but its se
23
23
  - [Nullable Primitives](#️-using-nullable-primitives)
24
24
  - [Unknown or Dynamic Data](#-working-with-unknown-or-dynamic-data)
25
25
  - [Using Raw JSON Strings](#️-using-raw-json-strings)
26
+ - [Using Enums](#️-working-with-enums)
26
27
  - [Custom Serializers](#️-using-custom-serializers-or-deserializers)
27
28
  - [Performance](#-performance)
28
29
  - [Debugging](#-debugging)
@@ -302,6 +303,23 @@ console.log(JSON.stringify(map));
302
303
  // Now its properly formatted JSON where pos's value is of type Vec3 not string!
303
304
  ```
304
305
 
306
+ ### 📝 Working with enums
307
+
308
+ By default, enums arn't supported by `json-as`. However, you can use a workaround:
309
+
310
+ ```typescript
311
+ namespace Foo {
312
+ export const bar = "a";
313
+ export const baz = "b";
314
+ export const gob = "c";
315
+ }
316
+
317
+ type Foo = string;
318
+
319
+ const serialized = JSON.stringify<Foo>(Foo.bar);
320
+ // "a"
321
+ ```
322
+
305
323
  ### ⚒️ Using custom serializers or deserializers
306
324
 
307
325
  This library supports custom serialization and deserialization methods, which can be defined using the `@serializer` and `@deserializer` decorators.
@@ -1,174 +1,145 @@
1
1
  import { JSON } from "..";
2
2
  import { describe, expect } from "./lib";
3
3
 
4
- // describe("Should serialize integer arrays", () => {
5
- // expect(JSON.stringify<u32[]>([0, 100, 101])).toBe("[0,100,101]");
6
-
7
- // expect(JSON.stringify<u64[]>([0, 100, 101])).toBe("[0,100,101]");
8
-
9
- // expect(JSON.stringify<i32[]>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
10
-
11
- // expect(JSON.stringify<i64[]>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
12
- // });
13
-
14
- // describe("Should serialize float arrays", () => {
15
- // expect(JSON.stringify<f64[]>([7.23, 10e2, 10e2, 123456e-5, 123456e-5, 0.0, 7.23])).toBe("[7.23,1000.0,1000.0,1.23456,1.23456,0.0,7.23]");
16
-
17
- // expect(JSON.stringify<f64[]>([1e21, 1e22, 1e-7, 1e-8, 1e-9])).toBe("[1e+21,1e+22,1e-7,1e-8,1e-9]");
18
- // });
19
-
20
- // describe("Should serialize boolean arrays", () => {
21
- // expect(JSON.stringify<bool[]>([true, false])).toBe("[true,false]");
22
-
23
- // expect(JSON.stringify<boolean[]>([true, false])).toBe("[true,false]");
24
- // });
25
-
26
- // describe("Should serialize string arrays", () => {
27
- // expect(JSON.stringify<string[]>(['string "with random spa\nces and \nnewlines\n\n\n'])).toBe('["string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"]');
28
- // });
29
-
30
- // describe("Should serialize nested integer arrays", () => {
31
- // expect(JSON.stringify<i64[][]>([[100, 101], [-100, -101], [0]])).toBe("[[100,101],[-100,-101],[0]]");
32
- // });
33
-
34
- // describe("Should serialize nested float arrays", () => {
35
- // expect(JSON.stringify<f64[][]>([[7.23], [10e2], [10e2], [123456e-5], [123456e-5], [0.0], [7.23]])).toBe("[[7.23],[1000.0],[1000.0],[1.23456],[1.23456],[0.0],[7.23]]");
36
- // });
37
-
38
- // describe("Should serialize nested boolean arrays", () => {
39
- // expect(JSON.stringify<bool[][]>([[true], [false]])).toBe("[[true],[false]]");
40
-
41
- // expect(JSON.stringify<boolean[][]>([[true], [false]])).toBe("[[true],[false]]");
42
- // });
43
-
44
- // describe("Should serialize object arrays", () => {
45
- // expect(
46
- // JSON.stringify<Vec3[]>([
47
- // {
48
- // x: 3.4,
49
- // y: 1.2,
50
- // z: 8.3,
51
- // },
52
- // {
53
- // x: 3.4,
54
- // y: -2.1,
55
- // z: 9.3,
56
- // },
57
- // ]),
58
- // ).toBe('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
59
- // });
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
- // });
4
+ describe("Should serialize integer arrays", () => {
5
+ expect(JSON.stringify<u32[]>([0, 100, 101])).toBe("[0,100,101]");
6
+
7
+ expect(JSON.stringify<u64[]>([0, 100, 101])).toBe("[0,100,101]");
8
+
9
+ expect(JSON.stringify<i32[]>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
10
+
11
+ expect(JSON.stringify<i64[]>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
12
+ });
13
+
14
+ describe("Should serialize float arrays", () => {
15
+ expect(JSON.stringify<f64[]>([7.23, 10e2, 10e2, 123456e-5, 123456e-5, 0.0, 7.23])).toBe("[7.23,1000.0,1000.0,1.23456,1.23456,0.0,7.23]");
16
+
17
+ expect(JSON.stringify<f64[]>([1e21, 1e22, 1e-7, 1e-8, 1e-9])).toBe("[1e+21,1e+22,1e-7,1e-8,1e-9]");
18
+ });
19
+
20
+ describe("Should serialize boolean arrays", () => {
21
+ expect(JSON.stringify<bool[]>([true, false])).toBe("[true,false]");
22
+
23
+ expect(JSON.stringify<boolean[]>([true, false])).toBe("[true,false]");
24
+ });
25
+
26
+ describe("Should serialize string arrays", () => {
27
+ expect(JSON.stringify<string[]>(['string "with random spa\nces and \nnewlines\n\n\n'])).toBe('["string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"]');
28
+ });
29
+
30
+ describe("Should serialize nested integer arrays", () => {
31
+ expect(JSON.stringify<i64[][]>([[100, 101], [-100, -101], [0]])).toBe("[[100,101],[-100,-101],[0]]");
32
+ });
33
+
34
+ describe("Should serialize nested float arrays", () => {
35
+ expect(JSON.stringify<f64[][]>([[7.23], [10e2], [10e2], [123456e-5], [123456e-5], [0.0], [7.23]])).toBe("[[7.23],[1000.0],[1000.0],[1.23456],[1.23456],[0.0],[7.23]]");
36
+ });
37
+
38
+ describe("Should serialize nested boolean arrays", () => {
39
+ expect(JSON.stringify<bool[][]>([[true], [false]])).toBe("[[true],[false]]");
40
+
41
+ expect(JSON.stringify<boolean[][]>([[true], [false]])).toBe("[[true],[false]]");
42
+ });
43
+
44
+ describe("Should serialize object arrays", () => {
45
+ expect(
46
+ JSON.stringify<Vec3[]>([
47
+ {
48
+ x: 3.4,
49
+ y: 1.2,
50
+ z: 8.3,
51
+ },
52
+ {
53
+ x: 3.4,
54
+ y: -2.1,
55
+ z: 9.3,
56
+ },
57
+ ]),
58
+ ).toBe('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
59
+ });
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
94
 
95
95
  describe("Should deserialize object arrays", () => {
96
96
  expect(JSON.stringify(JSON.parse<Vec3[]>('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]'))).toBe('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
97
97
  });
98
98
 
99
+ describe("Should deserialize raw arrays", () => {
100
+ const r1 = JSON.parse<JSON.Raw[]>('[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}]');
101
+ expect(r1[0].toString()).toBe('{"x":3.4,"y":1.2,"z":8.3}');
102
+ expect(r1[1].toString()).toBe('{"x":3.4,"y":-2.1,"z":9.3}');
103
+
104
+ const r2 = JSON.parse<JSON.Raw[][]>('[[{"x":3.4,"y":1.2,"z":8.3},{"x":3.4,"y":-2.1,"z":9.3}],[{"x":0.1,"y":-7.3,"z":4.5}]]');
105
+ expect(r2[0][0].toString()).toBe('{"x":3.4,"y":1.2,"z":8.3}');
106
+ expect(r2[0][1].toString()).toBe('{"x":3.4,"y":-2.1,"z":9.3}');
107
+ expect(r2[1][0].toString()).toBe('{"x":0.1,"y":-7.3,"z":4.5}');
108
+
109
+ const r3 = JSON.parse<JSON.Raw[]>("[1,2,3,4,5]");
110
+ expect(r3[0]).toBe(1);
111
+ expect(r3[1]).toBe(2);
112
+ expect(r3[2]).toBe(3);
113
+ expect(r3[3]).toBe(4);
114
+ expect(r3[4]).toBe(5);
115
+
116
+ const r4 = JSON.parse<JSON.Raw[][]>("[[1,2,3,4,5],[6,7,8,9,10]]");
117
+ expect(r4[0][0]).toBe(1);
118
+ expect(r4[0][1]).toBe(2);
119
+ expect(r4[0][2]).toBe(3);
120
+ expect(r4[0][3]).toBe(4);
121
+ expect(r4[0][4]).toBe(5);
122
+
123
+ expect(r4[1][0]).toBe(6);
124
+ expect(r4[1][1]).toBe(7);
125
+ expect(r4[1][2]).toBe(8);
126
+ expect(r4[1][3]).toBe(9);
127
+ expect(r4[1][4]).toBe(10);
128
+
129
+ const r5 = JSON.parse<JSON.Raw[]>('[{"x":3.4,"y":1.2,"z":8.3},[1,2,3,4,5],"12345",true,false,null,[[]]]');
130
+ expect(r5[0].toString()).toBe('{"x":3.4,"y":1.2,"z":8.3}');
131
+ expect(r5[1].toString()).toBe("[1,2,3,4,5]");
132
+ expect(r5[2]).toBe('"12345"');
133
+ expect(r5[3]).toBe(true);
134
+ expect(r5[4]).toBe(false);
135
+ expect(r5[5]).toBe(null);
136
+ expect(r5[6].toString()).toBe("[[]]");
137
+ });
138
+
99
139
 
100
140
  @json
101
141
  class Vec3 {
102
142
  x: f64 = 0.0;
103
143
  y: f64 = 0.0;
104
144
  z: f64 = 0.0;
105
- __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {
106
- let keyStart: usize = 0;
107
- let keyEnd: usize = 0;
108
- let isKey = false;
109
- let lastIndex: usize = 0;
110
-
111
- while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;
112
- while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
113
- if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
114
- if (load<u16>(srcStart) != 123) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
115
- if (load<u16>(srcEnd - 2) != 125) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
116
- srcStart += 2;
117
-
118
- while (srcStart < srcEnd) {
119
- let code = load<u16>(srcStart);
120
- while (JSON.Util.isSpace(code)) code = load<u16>((srcStart += 2));
121
- if (keyStart == 0) {
122
- if (code == 34 && load<u16>(srcStart - 2) !== 92) {
123
- if (isKey) {
124
- keyStart = lastIndex;
125
- keyEnd = srcStart;
126
- while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}
127
- if (code !== 58) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
128
- isKey = false;
129
- } else {
130
- isKey = true;
131
- lastIndex = srcStart + 2;
132
- }
133
- }
134
- srcStart += 2;
135
- } else {
136
- if (code - 48 <= 9 || code == 45) {
137
- lastIndex = srcStart;
138
- srcStart += 2;
139
- while (srcStart < srcEnd) {
140
- const code = load<u16>(srcStart);
141
- if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {
142
- switch (<u32>keyEnd - <u32>keyStart) {
143
- case 2: {
144
- const code16 = load<u16>(keyStart);
145
- if (code16 == 120) {
146
- // x
147
- store<f64>(changetype<usize>(out), JSON.__deserialize<f64>(lastIndex, srcStart), offsetof<this>("x"));
148
- keyStart = 0;
149
- break;
150
- } else if (code16 == 121) {
151
- // y
152
- store<f64>(changetype<usize>(out), JSON.__deserialize<f64>(lastIndex, srcStart), offsetof<this>("y"));
153
- keyStart = 0;
154
- break;
155
- } else if (code16 == 122) {
156
- // z
157
- store<f64>(changetype<usize>(out), JSON.__deserialize<f64>(lastIndex, srcStart), offsetof<this>("z"));
158
- keyStart = 0;
159
- break;
160
- }
161
- }
162
- }
163
- break;
164
- }
165
- srcStart += 2;
166
- }
167
- } else {
168
- srcStart += 2;
169
- }
170
- }
171
- }
172
- return out;
173
- }
174
145
  }
@@ -1,40 +1,49 @@
1
1
  import { JSON } from "..";
2
2
  import { describe, expect } from "./lib";
3
3
 
4
+
4
5
  @json
5
6
  class GenericTest<T> {
6
- public foo: T;
7
+ public foo: T;
7
8
 
8
- constructor(foo: T) {
9
- this.foo = foo;
10
- }
9
+ constructor(foo: T) {
10
+ this.foo = foo;
11
+ }
11
12
  }
12
13
 
14
+
13
15
  @json
14
16
  class Vec3 {
15
- public x!: i32;
16
- public y!: i32;
17
- public z!: i32;
17
+ public x!: i32;
18
+ public y!: i32;
19
+ public z!: i32;
18
20
  }
19
21
 
20
22
  describe("Should serialize generics", () => {
21
- expect(JSON.stringify(new GenericTest<string>("bar"))).toBe('{"foo":"bar"}');
22
- expect(JSON.stringify(new GenericTest<i32>(42))).toBe('{"foo":42}');
23
- expect(JSON.stringify(new GenericTest<boolean>(true))).toBe('{"foo":true}');
24
- expect(JSON.stringify(new GenericTest<Vec3>({ x: 1, y: 2, z: 3 }))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
25
- expect(JSON.stringify(new GenericTest<string[]>(["item1", "item2"]))).toBe('{"foo":["item1","item2"]}');
26
- expect(JSON.stringify(new GenericTest<Vec3[]>([{ x: 1, y: 2, z: 3 }, { x: 4, y: 5, z: 6 }]))).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
27
- expect(JSON.stringify(new GenericTest<i32[]>([1, 2, 3]))).toBe('{"foo":[1,2,3]}');
28
- expect(JSON.stringify(new GenericTest<boolean[]>([true, false, true]))).toBe('{"foo":[true,false,true]}');
23
+ expect(JSON.stringify(new GenericTest<string>("bar"))).toBe('{"foo":"bar"}');
24
+ expect(JSON.stringify(new GenericTest<i32>(42))).toBe('{"foo":42}');
25
+ expect(JSON.stringify(new GenericTest<boolean>(true))).toBe('{"foo":true}');
26
+ expect(JSON.stringify(new GenericTest<Vec3>({ x: 1, y: 2, z: 3 }))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
27
+ expect(JSON.stringify(new GenericTest<string[]>(["item1", "item2"]))).toBe('{"foo":["item1","item2"]}');
28
+ expect(
29
+ JSON.stringify(
30
+ new GenericTest<Vec3[]>([
31
+ { x: 1, y: 2, z: 3 },
32
+ { x: 4, y: 5, z: 6 },
33
+ ]),
34
+ ),
35
+ ).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
36
+ expect(JSON.stringify(new GenericTest<i32[]>([1, 2, 3]))).toBe('{"foo":[1,2,3]}');
37
+ expect(JSON.stringify(new GenericTest<boolean[]>([true, false, true]))).toBe('{"foo":[true,false,true]}');
29
38
  });
30
39
 
31
40
  describe("Should deserialize generics", () => {
32
- expect(JSON.parse<GenericTest<string>>('{"foo":"bar"}').foo).toBe("bar");
33
- expect(JSON.parse<GenericTest<i32>>('{"foo":42}').foo.toString()).toBe("42");
34
- expect(JSON.parse<GenericTest<boolean>>('{"foo":true}').foo).toBe(true);
35
- expect(JSON.stringify(JSON.parse<GenericTest<Vec3>>('{"foo":{"x":1,"y":2,"z":3}}'))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
36
- expect(JSON.stringify(JSON.parse<GenericTest<string[]>>('{"foo":["item1","item2"]}'))).toBe('{"foo":["item1","item2"]}');
37
- expect(JSON.stringify(JSON.parse<GenericTest<Vec3[]>>('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}'))).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
38
- expect(JSON.stringify(JSON.parse<GenericTest<i32[]>>('{"foo":[1,2,3]}'))).toBe('{"foo":[1,2,3]}');
39
- expect(JSON.stringify(JSON.parse<GenericTest<boolean[]>>('{"foo":[true,false,true]}'))).toBe('{"foo":[true,false,true]}');
41
+ expect(JSON.parse<GenericTest<string>>('{"foo":"bar"}').foo).toBe("bar");
42
+ expect(JSON.parse<GenericTest<i32>>('{"foo":42}').foo.toString()).toBe("42");
43
+ expect(JSON.parse<GenericTest<boolean>>('{"foo":true}').foo).toBe(true);
44
+ expect(JSON.stringify(JSON.parse<GenericTest<Vec3>>('{"foo":{"x":1,"y":2,"z":3}}'))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
45
+ expect(JSON.stringify(JSON.parse<GenericTest<string[]>>('{"foo":["item1","item2"]}'))).toBe('{"foo":["item1","item2"]}');
46
+ expect(JSON.stringify(JSON.parse<GenericTest<Vec3[]>>('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}'))).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
47
+ expect(JSON.stringify(JSON.parse<GenericTest<i32[]>>('{"foo":[1,2,3]}'))).toBe('{"foo":[1,2,3]}');
48
+ expect(JSON.stringify(JSON.parse<GenericTest<boolean[]>>('{"foo":[true,false,true]}'))).toBe('{"foo":[true,false,true]}');
40
49
  });
@@ -13,7 +13,7 @@ export function expect<T>(left: T): Expectation {
13
13
  // @ts-ignore
14
14
  if (!isDefined(left.toString)) throw new Error("Expected left to have a toString method, but it does not.");
15
15
  // @ts-ignore
16
- return new Expectation(left == null ? "null" : left.toString());
16
+ return new Expectation(isNull(left) ? "null" : left.toString());
17
17
  }
18
18
 
19
19
  class Expectation {
@@ -26,12 +26,16 @@ class Expectation {
26
26
  // @ts-ignore
27
27
  if (!isDefined(right.toString)) throw new Error("Expected right to have a toString method, but it does not.");
28
28
  // @ts-ignore
29
- if (this.left != (right == null ? "null" : right.toString())) {
29
+ if (this.left != (isNull(right) ? "null" : right.toString())) {
30
30
  console.log(" " + currentDescription + "\n");
31
31
  // @ts-ignore
32
- console.log(" (expected) -> " + (right == null ? "null" : right.toString()));
32
+ console.log(" (expected) -> " + (isNull(right) ? "null" : right.toString()));
33
33
  console.log(" (received) -> " + this.left);
34
34
  unreachable();
35
35
  }
36
36
  }
37
37
  }
38
+
39
+ function isNull<T>(value: T): bool {
40
+ return (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && value == 0) || (isNullable<T>() && changetype<usize>(value) == <usize>0);
41
+ }
@@ -2,14 +2,20 @@ import { JSON } from "..";
2
2
  import { describe, expect } from "./lib";
3
3
  import { Vec3 } from "./types";
4
4
 
5
+
5
6
  @json
6
7
  class Player {
8
+
7
9
  @alias("first name")
8
10
  firstName!: string;
9
11
  lastName!: string;
10
12
  lastActive!: i32[];
13
+
14
+
11
15
  @omitif((self: Player) => self.age < 18)
12
16
  age!: i32;
17
+
18
+
13
19
  @omitnull()
14
20
  pos!: Vec3 | null;
15
21
  isVerified!: boolean;
@@ -28,20 +34,22 @@ const player: Player = {
28
34
  isVerified: true,
29
35
  };
30
36
 
37
+
31
38
  @json
32
39
  class Foo {
33
- bar: Bar = new Bar();
40
+ bar: Bar = new Bar();
34
41
  }
35
42
 
43
+
36
44
  @json
37
45
  class Bar {
38
- baz: string = "buz"
46
+ baz: string = "buz";
39
47
  }
40
48
 
41
49
  describe("Should resolve imported schemas", () => {
42
- expect(JSON.stringify(player)).toBe('{"age":18,"pos":{"x":3.4,"y":1.2,"z":8.3},"first name":"Jairus","lastName":"Tanaka","lastActive":[3,9,2025],"isVerified":true}');
50
+ expect(JSON.stringify(player)).toBe('{"age":18,"pos":{"x":3.4,"y":1.2,"z":8.3},"first name":"Jairus","lastName":"Tanaka","lastActive":[3,9,2025],"isVerified":true}');
43
51
  });
44
52
 
45
53
  describe("Should resolve local schemas", () => {
46
- expect(JSON.stringify(new Foo())).toBe('{"bar":{"baz":"buz"}}');
47
- });
54
+ expect(JSON.stringify(new Foo())).toBe('{"bar":{"baz":"buz"}}');
55
+ });
@@ -0,0 +1,12 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+
4
+ describe("Should serialize integer static arrays", () => {
5
+ expect(JSON.stringify<StaticArray<u32>>([0, 100, 101])).toBe("[0,100,101]");
6
+
7
+ expect(JSON.stringify<StaticArray<u64>>([0, 100, 101])).toBe("[0,100,101]");
8
+
9
+ expect(JSON.stringify<StaticArray<i32>>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
10
+
11
+ expect(JSON.stringify<StaticArray<i64>>([0, 100, 101, -100, -101])).toBe("[0,100,101,-100,-101]");
12
+ });
@@ -7,6 +7,7 @@ type StringAlias2 = StringAlias1;
7
7
  type StringAlias3 = StringAlias2;
8
8
  type StringAlias4 = StringAlias3;
9
9
 
10
+
10
11
  @json
11
12
  class Alias {
12
13
  public foo: StringAlias4 = "";
@@ -18,9 +19,9 @@ class Alias {
18
19
  const alias = new Alias("bar");
19
20
 
20
21
  describe("Should serialize with type aliases", () => {
21
- expect(JSON.stringify(alias)).toBe('{"foo":"bar"}');
22
+ expect(JSON.stringify(alias)).toBe('{"foo":"bar"}');
22
23
  });
23
24
 
24
25
  describe("Should deserialize with type aliases", () => {
25
- expect(JSON.stringify(JSON.parse<Alias>('{"foo":"bar"}'))).toBe('{"foo":"bar"}');
26
+ expect(JSON.stringify(JSON.parse<Alias>('{"foo":"bar"}'))).toBe('{"foo":"bar"}');
26
27
  });
@@ -0,0 +1,106 @@
1
+ import { isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_RIGHT, QUOTE, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BACK_SLASH, CHAR_T, CHAR_F, CHAR_N } from "../../../custom/chars";
3
+ import { JSON } from "../../..";
4
+ import { ptrToStr } from "../../../util/ptrToStr";
5
+
6
+ export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize): JSON.Raw[] {
7
+ // console.log("data: " + ptrToStr(srcStart, srcEnd));
8
+ const out = changetype<JSON.Raw[]>(dst || changetype<usize>(instantiate<JSON.Raw[]>()));
9
+ let lastIndex: usize = 0;
10
+ let depth = 0;
11
+ srcStart += 2;
12
+ while (srcStart < srcEnd) {
13
+ let code = load<u16>(srcStart);
14
+ if (code == QUOTE) {
15
+ lastIndex = srcStart;
16
+ srcStart += 2;
17
+ while (srcStart < srcEnd) {
18
+ code = load<u16>(srcStart);
19
+ if (code == QUOTE || isSpace(code)) {
20
+ // console.log("Value (string): " + ptrToStr(lastIndex, srcStart));
21
+ out.push(JSON.Raw.from(ptrToStr(lastIndex, srcStart + 2)));
22
+ // while (isSpace(load<u16>((srcStart += 2)))) {
23
+ // /* empty */
24
+ // }
25
+ srcStart += 4;
26
+ break;
27
+ }
28
+ srcStart += 2;
29
+ }
30
+ } else if (code - 48 <= 9 || code == 45) {
31
+ lastIndex = srcStart;
32
+ srcStart += 2;
33
+ while (srcStart < srcEnd) {
34
+ const code = load<u16>(srcStart);
35
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
36
+ // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
37
+ out.push(JSON.Raw.from(ptrToStr(lastIndex, srcStart)));
38
+ srcStart += 2;
39
+ break;
40
+ }
41
+ srcStart += 2;
42
+ }
43
+ } else if (code == BRACE_LEFT) {
44
+ lastIndex = srcStart;
45
+ depth++;
46
+ srcStart += 2;
47
+ while (srcStart < srcEnd) {
48
+ const code = load<u16>(srcStart);
49
+ if (code == QUOTE) {
50
+ srcStart += 2;
51
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
52
+ } else if (code == BRACE_RIGHT) {
53
+ if (--depth == 0) {
54
+ // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
55
+ out.push(JSON.Raw.from(ptrToStr(lastIndex, srcStart + 2)));
56
+ srcStart += 4;
57
+ break;
58
+ }
59
+ } else if (code == BRACE_LEFT) depth++;
60
+ srcStart += 2;
61
+ }
62
+ } else if (code == BRACKET_LEFT) {
63
+ lastIndex = srcStart;
64
+ depth++;
65
+ srcStart += 2;
66
+ while (srcStart < srcEnd) {
67
+ const code = load<u16>(srcStart);
68
+ if (code == QUOTE) {
69
+ srcStart += 2;
70
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
71
+ } else if (code == BRACKET_RIGHT) {
72
+ if (--depth == 0) {
73
+ // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
74
+ out.push(JSON.Raw.from(ptrToStr(lastIndex, srcStart + 2)));
75
+ srcStart += 4;
76
+ break;
77
+ }
78
+ } else if (code == BRACKET_LEFT) depth++;
79
+ srcStart += 2;
80
+ }
81
+ } else if (code == CHAR_T) {
82
+ if (load<u64>(srcStart) == 28429475166421108) {
83
+ // console.log("Value (true): " + ptrToStr(srcStart, srcStart + 8));
84
+ out.push(JSON.Raw.from("true"));
85
+ srcStart += 10;
86
+ }
87
+ } else if (code == CHAR_F) {
88
+ if (load<u64>(srcStart, 2) == 28429466576093281) {
89
+ // console.log("Value (false): " + ptrToStr(srcStart, srcStart + 10));
90
+ out.push(JSON.Raw.from("false"));
91
+ srcStart += 12;
92
+ }
93
+ } else if (code == CHAR_N) {
94
+ if (load<u64>(srcStart) == 30399761348886638) {
95
+ // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
96
+ out.push(JSON.Raw.from("null"));
97
+ srcStart += 10;
98
+ }
99
+ } else if (isSpace(code)) {
100
+ srcStart += 2;
101
+ } else {
102
+ throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString() + " " + ptrToStr(lastIndex, srcStart + 10));
103
+ }
104
+ }
105
+ return out;
106
+ }