json-as 0.9.20 → 0.9.21

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 CHANGED
@@ -28,6 +28,7 @@ v0.9.17 - A schema's parent's fields should be included properly
28
28
  v0.9.18 - Should be able to use @alias and @omit*** or JSON.Raw
29
29
  v0.9.19 - Fix arguments in @omitif declarations not working properly
30
30
  v0.9.20 - Strings were being received with quotes attached via the toString functionality. Removed that.
31
+ v0.9.21 - Fix #89
31
32
 
32
33
  [UNRELEASED] v1.0.0
33
34
  - Allow nullable primitives
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  __| || __|| || | | ___ | _ || __|
4
4
  | | ||__ || | || | | ||___|| ||__ |
5
5
  |_____||_____||_____||_|___| |__|__||_____|
6
- v0.9.20
6
+ v0.9.21
7
7
  </pre>
8
8
  </h5>
9
9
 
@@ -107,25 +107,16 @@ const serialized = JSON.stringify(arr);
107
107
  const parsed = JSON.parse<Base[]>(serialized);
108
108
  ```
109
109
 
110
- Classes can even have inheritance. Here's a nasty example
111
-
112
- ```js
113
- @json
114
- class Base {}
115
-
116
- const serialized = JSON.stringify(arr);
117
- // [{"x":1.0},{"x":1.0,"y":2.0},{"y":2.0,"x":1.0,"z":3.0}]
118
- const parsed = JSON.parse<Base[]>(serialized);
119
- ```
120
-
121
110
  You can also add it to your `asconfig.json`
122
111
 
112
+ ```json
123
113
  {
124
- // ...
125
- "options": {
126
- "transform": ["json-as/transform"]
127
- }
114
+ // ...
115
+ "options": {
116
+ "transform": ["json-as/transform"]
117
+ }
128
118
  }
119
+ ````
129
120
 
130
121
  If you use this project in your codebase, consider dropping a [star](https://github.com/JairusSW/as-json). I would really appreciate it!
131
122
 
@@ -0,0 +1,20 @@
1
+ import { JSON } from "json-as";
2
+ import { describe, expect, run } from "as-test/assembly";
3
+
4
+ describe("Should serialize booleans", () => {
5
+ expect(JSON.stringify<bool>(true)).toBe("true");
6
+
7
+ expect(JSON.stringify<bool>(false)).toBe("false");
8
+
9
+ expect(JSON.stringify<boolean>(true)).toBe("true");
10
+
11
+ expect(JSON.stringify<boolean>(false)).toBe("false");
12
+ });
13
+
14
+ describe("Should deserialize booleans", () => {
15
+ expect(JSON.parse<boolean>("true")).toBe(true);
16
+
17
+ expect(JSON.parse<boolean>("false")).toBe(false);
18
+ });
19
+
20
+ run();
@@ -0,0 +1,52 @@
1
+ import { JSON } from "json-as";
2
+ import { describe, expect, run } from "as-test/assembly";
3
+
4
+ describe("Should serialize floats", () => {
5
+ expect(JSON.stringify<f64>(7.23)).toBe("7.23");
6
+
7
+ expect(JSON.stringify<f64>(10e2)).toBe("1000.0");
8
+
9
+ expect(JSON.stringify<f64>(123456e-5)).toBe("1.23456");
10
+
11
+ expect(JSON.stringify<f64>(0.0)).toBe("0.0");
12
+
13
+ expect(JSON.stringify<f64>(-7.23)).toBe("-7.23");
14
+
15
+ expect(JSON.stringify<f64>(1e-6)).toBe("0.000001");
16
+
17
+ expect(JSON.stringify<f64>(1e-7)).toBe("1e-7");
18
+
19
+ expect(JSON.parse<f64>("1E-7")).toBe(1e-7);
20
+
21
+ expect(JSON.stringify<f64>(1e20)).toBe("100000000000000000000.0");
22
+
23
+ expect(JSON.stringify<f64>(1e21)).toBe("1e+21");
24
+
25
+ expect(JSON.parse<f64>("1E+21")).toBe(1e21);
26
+
27
+ expect(JSON.parse<f64>("1e21")).toBe(1e21);
28
+
29
+ expect(JSON.parse<f64>("1E21")).toBe(1e21);
30
+ });
31
+
32
+ describe("Should deserialize floats", () => {
33
+ expect(JSON.parse<f64>("7.23")).toBe(7.23);
34
+
35
+ expect(JSON.parse<f64>("1000.0")).toBe(1000.0);
36
+
37
+ expect(JSON.parse<f64>("1.23456")).toBe(1.23456);
38
+
39
+ expect(JSON.parse<f64>("0.0")).toBe(0.0);
40
+
41
+ expect(JSON.parse<f64>("-7.23")).toBe(-7.23);
42
+
43
+ expect(JSON.parse<f64>("0.000001")).toBe(0.000001);
44
+
45
+ expect(JSON.parse<f64>("1e-7")).toBe(1e-7);
46
+
47
+ expect(JSON.parse<f64>("100000000000000000000.0")).toBe(1e20);
48
+
49
+ expect(JSON.parse<f64>("1e+21")).toBe(1e21);
50
+ });
51
+
52
+ run();
@@ -0,0 +1,28 @@
1
+ import { JSON } from "json-as";
2
+ import { describe, expect, run } from "as-test/assembly";
3
+
4
+ describe("Should serialize integers", () => {
5
+ expect(JSON.stringify(0)).toBe("0");
6
+
7
+ expect(JSON.stringify<u32>(100)).toBe("100");
8
+
9
+ expect(JSON.stringify<u64>(101)).toBe("101");
10
+
11
+ expect(JSON.stringify<i32>(-100)).toBe("-100");
12
+
13
+ expect(JSON.stringify<i64>(-101)).toBe("-101");
14
+ });
15
+
16
+ describe("Should deserialize integers", () => {
17
+ expect(JSON.parse<i32>("0")).toBe(<i32>0);
18
+
19
+ expect(JSON.parse<u32>("100")).toBe(<u32>100);
20
+
21
+ expect(JSON.parse<u64>("101")).toBe(<u64>101);
22
+
23
+ expect(JSON.parse<i32>("-100")).toBe(<i32>-100);
24
+
25
+ expect(JSON.parse<i64>("-101")).toBe(<i64>-101);
26
+ });
27
+
28
+ run();
@@ -0,0 +1,5 @@
1
+ import { JSON } from "json-as";
2
+ import { describe, expect, run } from "as-test/assembly";
3
+
4
+
5
+ run();
@@ -0,0 +1,48 @@
1
+ import { JSON } from "json-as";
2
+ import { describe, expect, run } from "as-test/assembly";
3
+
4
+ describe("Should serialize strings", () => {
5
+ expect(JSON.stringify("abcdefg")).toBe('"abcdefg"');
6
+
7
+ expect(JSON.stringify('st"ring" w""ith quotes"')).toBe(
8
+ '"st\\"ring\\" w\\"\\"ith quotes\\""',
9
+ );
10
+
11
+ expect(
12
+ JSON.stringify('string "with random spa\nces and \nnewlines\n\n\n'),
13
+ ).toBe('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"');
14
+
15
+ expect(
16
+ JSON.stringify(
17
+ 'string with colon : comma , brace [ ] bracket { } and quote " and other quote \\"',
18
+ ),
19
+ ).toBe(
20
+ '"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\\\\\""',
21
+ );
22
+ });
23
+
24
+ describe("Should deserialize strings", () => {
25
+ expect(JSON.parse<string>('"abcdefg"')).toBe("abcdefg");
26
+
27
+ expect(
28
+ JSON.parse<string>(
29
+ '"\\"st\\\\\\"ring\\\\\\" w\\\\\\"\\\\\\"ith quotes\\\\\\"\\""',
30
+ ),
31
+ ).toBe('"st\\"ring\\" w\\"\\"ith quotes\\""');
32
+
33
+ expect(
34
+ JSON.parse<string>(
35
+ '"\\"string \\\\\\"with random spa\\\\nces and \\\\nnewlines\\\\n\\\\n\\\\n\\""',
36
+ ),
37
+ ).toBe('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"');
38
+
39
+ expect(
40
+ JSON.parse<string>(
41
+ '"\\"string with colon : comma , brace [ ] bracket { } and quote \\\\\\" and other quote \\\\\\\\\\"\\""',
42
+ ),
43
+ ).toBe(
44
+ '"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\\\""',
45
+ );
46
+ });
47
+
48
+ run();
@@ -10,76 +10,6 @@ import {
10
10
  Vec3,
11
11
  } from "./types";
12
12
 
13
- describe("Should serialize strings", () => {
14
- expect(JSON.stringify("abcdefg")).toBe('"abcdefg"');
15
-
16
- expect(JSON.stringify('st"ring" w""ith quotes"')).toBe(
17
- '"st\\"ring\\" w\\"\\"ith quotes\\""',
18
- );
19
-
20
- expect(
21
- JSON.stringify('string "with random spa\nces and \nnewlines\n\n\n'),
22
- ).toBe('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"');
23
-
24
- expect(
25
- JSON.stringify(
26
- 'string with colon : comma , brace [ ] bracket { } and quote " and other quote \\"',
27
- ),
28
- ).toBe(
29
- '"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\\\\\""',
30
- );
31
- });
32
-
33
- describe("Should serialize integers", () => {
34
- expect(JSON.stringify(0)).toBe("0");
35
-
36
- expect(JSON.stringify<u32>(100)).toBe("100");
37
-
38
- expect(JSON.stringify<u64>(101)).toBe("101");
39
-
40
- expect(JSON.stringify<i32>(-100)).toBe("-100");
41
-
42
- expect(JSON.stringify<i64>(-101)).toBe("-101");
43
- });
44
-
45
- describe("Should serialize floats", () => {
46
- expect(JSON.stringify<f64>(7.23)).toBe("7.23");
47
-
48
- expect(JSON.stringify<f64>(10e2)).toBe("1000.0");
49
-
50
- expect(JSON.stringify<f64>(123456e-5)).toBe("1.23456");
51
-
52
- expect(JSON.stringify<f64>(0.0)).toBe("0.0");
53
-
54
- expect(JSON.stringify<f64>(-7.23)).toBe("-7.23");
55
-
56
- expect(JSON.stringify<f64>(1e-6)).toBe("0.000001");
57
-
58
- expect(JSON.stringify<f64>(1e-7)).toBe("1e-7");
59
-
60
- expect(JSON.parse<f64>("1E-7")).toBe(1e-7);
61
-
62
- expect(JSON.stringify<f64>(1e20)).toBe("100000000000000000000.0");
63
-
64
- expect(JSON.stringify<f64>(1e21)).toBe("1e+21");
65
-
66
- expect(JSON.parse<f64>("1E+21")).toBe(1e21);
67
-
68
- expect(JSON.parse<f64>("1e21")).toBe(1e21);
69
-
70
- expect(JSON.parse<f64>("1E21")).toBe(1e21);
71
- });
72
-
73
- describe("Should serialize booleans", () => {
74
- expect(JSON.stringify<bool>(true)).toBe("true");
75
-
76
- expect(JSON.stringify<bool>(false)).toBe("false");
77
-
78
- expect(JSON.stringify<boolean>(true)).toBe("true");
79
-
80
- expect(JSON.stringify<boolean>(false)).toBe("false");
81
- });
82
-
83
13
  describe("Should serialize class inheritance", () => {
84
14
  const obj = new DerivedObject("1", "2");
85
15
 
@@ -225,69 +155,6 @@ describe("Should serialize @omit'ed objects", () => {
225
155
  }),
226
156
  ).toBe('{"x":1,"y":1,"z":1}');
227
157
  });
228
-
229
- describe("Should deserialize strings", () => {
230
- expect(JSON.parse<string>('"abcdefg"')).toBe("abcdefg");
231
-
232
- expect(
233
- JSON.parse<string>(
234
- '"\\"st\\\\\\"ring\\\\\\" w\\\\\\"\\\\\\"ith quotes\\\\\\"\\""',
235
- ),
236
- ).toBe('"st\\"ring\\" w\\"\\"ith quotes\\""');
237
-
238
- expect(
239
- JSON.parse<string>(
240
- '"\\"string \\\\\\"with random spa\\\\nces and \\\\nnewlines\\\\n\\\\n\\\\n\\""',
241
- ),
242
- ).toBe('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"');
243
-
244
- expect(
245
- JSON.parse<string>(
246
- '"\\"string with colon : comma , brace [ ] bracket { } and quote \\\\\\" and other quote \\\\\\\\\\"\\""',
247
- ),
248
- ).toBe(
249
- '"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\\\""',
250
- );
251
- });
252
-
253
- describe("Should deserialize integers", () => {
254
- expect(JSON.parse<i32>("0")).toBe(<i32>0);
255
-
256
- expect(JSON.parse<u32>("100")).toBe(<u32>100);
257
-
258
- expect(JSON.parse<u64>("101")).toBe(<u64>101);
259
-
260
- expect(JSON.parse<i32>("-100")).toBe(<i32>-100);
261
-
262
- expect(JSON.parse<i64>("-101")).toBe(<i64>-101);
263
- });
264
-
265
- describe("Should deserialize floats", () => {
266
- expect(JSON.parse<f64>("7.23")).toBe(7.23);
267
-
268
- expect(JSON.parse<f64>("1000.0")).toBe(1000.0);
269
-
270
- expect(JSON.parse<f64>("1.23456")).toBe(1.23456);
271
-
272
- expect(JSON.parse<f64>("0.0")).toBe(0.0);
273
-
274
- expect(JSON.parse<f64>("-7.23")).toBe(-7.23);
275
-
276
- expect(JSON.parse<f64>("0.000001")).toBe(0.000001);
277
-
278
- expect(JSON.parse<f64>("1e-7")).toBe(1e-7);
279
-
280
- expect(JSON.parse<f64>("100000000000000000000.0")).toBe(1e20);
281
-
282
- expect(JSON.parse<f64>("1e+21")).toBe(1e21);
283
- });
284
-
285
- describe("Should deserialize booleans", () => {
286
- expect(JSON.parse<boolean>("true")).toBe(true);
287
-
288
- expect(JSON.parse<boolean>("false")).toBe(false);
289
- });
290
-
291
158
  describe("Should deserialize class inheritance", () => {
292
159
  const jsonStr = '{"a":"1","b":"2"}';
293
160
  const obj = JSON.parse<DerivedObject>(jsonStr);
package/assembly/index.ts CHANGED
@@ -156,6 +156,179 @@ export namespace JSON {
156
156
  @inline static from<T>(value: T): Box<T> {
157
157
  return new Box(value);
158
158
  }
159
+ @inline
160
+ @operator("==")
161
+ eq(other: this): bool {
162
+ if (isNullable<T>() && changetype<usize>(this) == <usize>0) {
163
+ if (changetype<usize>(other) == <usize>0) return true;
164
+ }
165
+ return this.value == other.value;
166
+ }
167
+
168
+ @inline
169
+ @operator("!=")
170
+ notEq(other: this): bool {
171
+ if (isNullable<T>() && changetype<usize>(this) == <usize>0) {
172
+ if (changetype<usize>(this) == changetype<usize>(other)) return true;
173
+ }
174
+ return this.value != other.value;
175
+ }
176
+
177
+ @inline
178
+ @operator(">")
179
+ gt(other: this): bool {
180
+ return this._val > other._val;
181
+ }
182
+
183
+ @inline
184
+ @operator(">=")
185
+ ge(other: this): bool {
186
+ return this._val >= other._val;
187
+ }
188
+
189
+ @inline
190
+ @operator("<")
191
+ lt(other: this): bool {
192
+ return this._val < other._val;
193
+ }
194
+
195
+ @inline
196
+ @operator("<=")
197
+ le(other: this): bool {
198
+ return this._val <= other._val;
199
+ }
200
+
201
+ @inline
202
+ @operator(">>")
203
+ shr(other: this): this {
204
+ // @ts-ignore
205
+ return instantiate<this>(this._val >> other._val);
206
+ }
207
+
208
+ @inline
209
+ @operator(">>>")
210
+ shr_u(other: this): this {
211
+ // @ts-ignore
212
+ return instantiate<this>(this._val >>> other._val);
213
+ }
214
+
215
+ @inline
216
+ @operator("<<")
217
+ shl(other: this): this {
218
+ // @ts-ignore
219
+ return instantiate<this>(this._val << other._val);
220
+ }
221
+
222
+ @inline
223
+ @operator("&")
224
+ and(other: this): this {
225
+ // @ts-ignore
226
+ return instantiate<this>(this._val & other._val);
227
+ }
228
+
229
+ @inline
230
+ @operator("|")
231
+ or(other: this): this {
232
+ // @ts-ignore
233
+ return instantiate<this>(this._val | other._val);
234
+ }
235
+
236
+ @inline
237
+ @operator("^")
238
+ xor(other: this): this {
239
+ // @ts-ignore
240
+ return instantiate<this>(this._val ^ other._val);
241
+ }
242
+
243
+ @inline
244
+ @operator("+")
245
+ add(other: this): this {
246
+ // @ts-ignore
247
+ return instantiate<this>(this._val + other._val);
248
+ }
249
+
250
+ @inline
251
+ @operator("-")
252
+ sub(other: this): this {
253
+ // @ts-ignore
254
+ return instantiate<this>(this._val - other._val);
255
+ }
256
+
257
+ @inline
258
+ @operator("*")
259
+ mul(other: this): this {
260
+ // @ts-ignore
261
+ return instantiate<this>(this._val * other._val);
262
+ }
263
+
264
+ @inline
265
+ @operator("/")
266
+ div(other: this): this {
267
+ // @ts-ignore
268
+ return instantiate<this>(this._val / other._val);
269
+ }
270
+
271
+ @inline
272
+ @operator("**")
273
+ pow(other: this): this {
274
+ // @ts-ignore
275
+ return instantiate<this>((this._val ** other._val) as T);
276
+ }
277
+
278
+ @inline
279
+ @operator("%")
280
+ rem(other: this): this {
281
+ // @ts-ignore
282
+ return instantiate<this>(this._val % other._val);
283
+ }
284
+
285
+ @inline
286
+ @operator.prefix("!")
287
+ isEmpty(): bool {
288
+ return !this._val;
289
+ }
290
+
291
+ @inline
292
+ @operator.prefix("~")
293
+ not(): this {
294
+ return instantiate<this>(~this._val);
295
+ }
296
+
297
+ @inline
298
+ @operator.prefix("+")
299
+ pos(): this {
300
+ return instantiate<this>(+this._val);
301
+ }
302
+
303
+ @inline
304
+ @operator.prefix("-")
305
+ neg(): this {
306
+ return instantiate<this>(-this._val);
307
+ }
308
+
309
+ @operator.prefix("++")
310
+ preInc(): this {
311
+ // @ts-ignore
312
+ ++this._val;
313
+ return this;
314
+ }
315
+
316
+ @operator.prefix("--")
317
+ preDec(): this {
318
+ // @ts-ignore
319
+ --this._val;
320
+ return this;
321
+ }
322
+
323
+ @operator.postfix("++")
324
+ postInc(): this {
325
+ return this.clone().preInc();
326
+ }
327
+
328
+ @operator.postfix("--")
329
+ postDec(): this {
330
+ return this.clone().preDec();
331
+ }
159
332
  }
160
333
 
161
334
  /**
package/assembly/test.ts CHANGED
@@ -1,29 +1,14 @@
1
1
  // import { JSON } from ".";
2
2
  import { JSON } from ".";
3
- @json
4
- class Message {
5
- @alias("raw_foo")
6
- public raw: JSON.Raw = "[1,2,3]";
7
- constructor(role: string, content: string) {
8
- this._role = role;
9
- this.content = content;
10
- }
11
-
12
- @alias("role")
13
- protected _role: string;
14
-
15
- get role(): string {
16
- return this._role;
17
- }
18
3
 
19
- content: string;
4
+ @json
5
+ class ContentBlock {
6
+ @omitnull()
7
+ input: JSON.Raw | null = null;
20
8
  }
21
9
 
22
- @json
23
- class UserMessage extends Message {
24
- constructor(content: string) {
25
- super("user", content);
26
- }
10
+ const foo: ContentBlock = {
11
+ input: "123"
27
12
  }
28
- console.log(JSON.stringify(new Message("user", "foo")));
29
- console.log(JSON.stringify(new UserMessage("foo")));
13
+
14
+ console.log(JSON.stringify(foo))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.9.20",
3
+ "version": "0.9.21",
4
4
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -87,9 +87,12 @@ class JSONTransform extends BaseVisitor {
87
87
  mem.type = type;
88
88
  mem.value = value;
89
89
  mem.node = member;
90
- if (type == "JSON.Raw") {
90
+ if (type.includes("JSON.Raw")) {
91
91
  mem.flags.set(PropertyFlags.JSON_Raw, []);
92
92
  }
93
+ if (member.type.isNullable) {
94
+ mem.flags.set(PropertyFlags.Null, []);
95
+ }
93
96
  if (member.decorators) {
94
97
  for (const decorator of member.decorators) {
95
98
  const decoratorName = decorator.name.text;
@@ -214,32 +217,31 @@ class JSONTransform extends BaseVisitor {
214
217
  "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
215
218
  }
216
219
  else {
217
- SERIALIZE_RAW += "`;\n};";
218
- SERIALIZE_PRETTY += "`;\n};";
220
+ SERIALIZE_RAW += "}`;\n return out;\n}";
221
+ SERIALIZE_PRETTY += "}`;\n return out;\n}";
219
222
  }
220
223
  INITIALIZE += " return this;\n}";
221
224
  const sortedMembers = [];
222
- const _sorted = schema.members.sort((a, b) => a.name.length - b.name.length);
223
- let len = 0;
224
- let offset = 0;
225
- sortedMembers.push([_sorted[0]]);
226
- len = _sorted[0]?.name.length;
227
- for (let i = 1; i < _sorted.length; i++) {
225
+ const _sorted = schema.members.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length));
226
+ let len = -1;
227
+ let offset = -1;
228
+ for (let i = 0; i < _sorted.length; i++) {
228
229
  const member = _sorted[i];
229
- if (member.alias?.length || member.name.length > len) {
230
- sortedMembers.push([member]);
231
- len = member.alias?.length || member.name.length;
232
- offset++;
230
+ const _name = member.alias || member.name;
231
+ if (_name.length === len) {
232
+ sortedMembers[offset]?.push(member);
233
233
  }
234
234
  else {
235
- sortedMembers[offset].push(member);
235
+ sortedMembers.push([member]);
236
+ len = _name.length;
237
+ offset++;
236
238
  }
237
239
  }
238
240
  let first = true;
239
241
  for (const memberSet of sortedMembers) {
240
242
  const firstMember = memberSet[0];
241
- const name = encodeKey(firstMember.alias || firstMember.name);
242
- if (name.length === 1) {
243
+ const _name = encodeKey(firstMember.alias || firstMember.name);
244
+ if (_name.length === 1) {
243
245
  if (first) {
244
246
  DESERIALIZE +=
245
247
  " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
@@ -250,7 +252,7 @@ class JSONTransform extends BaseVisitor {
250
252
  "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
251
253
  }
252
254
  }
253
- else if (name.length === 2) {
255
+ else if (_name.length === 2) {
254
256
  if (first) {
255
257
  DESERIALIZE +=
256
258
  " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
@@ -261,7 +263,7 @@ class JSONTransform extends BaseVisitor {
261
263
  "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
262
264
  }
263
265
  }
264
- else if (name.length === 4) {
266
+ else if (_name.length === 4) {
265
267
  if (first) {
266
268
  DESERIALIZE +=
267
269
  " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
@@ -274,11 +276,11 @@ class JSONTransform extends BaseVisitor {
274
276
  }
275
277
  else {
276
278
  if (first) {
277
- DESERIALIZE += " if (" + name.length + " === len) {\n";
279
+ DESERIALIZE += " if (" + _name.length + " === len) {\n";
278
280
  first = false;
279
281
  }
280
282
  else {
281
- DESERIALIZE += "else if (" + name.length + " === len) {\n";
283
+ DESERIALIZE += "else if (" + _name.length + " === len) {\n";
282
284
  }
283
285
  }
284
286
  let f = true;
@@ -286,40 +288,40 @@ class JSONTransform extends BaseVisitor {
286
288
  const member = memberSet[i];
287
289
  if (!member.deserialize)
288
290
  continue;
289
- const name = encodeKey(member.alias || member.name);
290
- if (name.length === 1) {
291
- DESERIALIZE += ` case ${name.charCodeAt(0)}: {\n ${member.deserialize}\n return true;\n }\n`;
291
+ const _name = encodeKey(member.alias || member.name);
292
+ if (_name.length === 1) {
293
+ DESERIALIZE += ` case ${_name.charCodeAt(0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
292
294
  }
293
- else if (name.length === 2) {
294
- DESERIALIZE += ` case ${charCodeAt32(name, 0)}: {\n ${member.deserialize}\n return true;\n }\n`;
295
+ else if (_name.length === 2) {
296
+ DESERIALIZE += ` case ${charCodeAt32(_name, 0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
295
297
  }
296
- else if (name.length === 4) {
298
+ else if (_name.length === 4) {
297
299
  if (f) {
298
300
  f = false;
299
- DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
301
+ DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
300
302
  }
301
303
  else {
302
304
  DESERIALIZE =
303
305
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
304
- `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
306
+ `else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
305
307
  }
306
308
  }
307
309
  else {
308
310
  if (f) {
309
311
  f = false;
310
- DESERIALIZE += ` if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
312
+ DESERIALIZE += ` if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
311
313
  }
312
314
  else {
313
315
  DESERIALIZE =
314
316
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
315
- ` else if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
317
+ ` else if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
316
318
  }
317
319
  }
318
320
  }
319
- if (name.length < 3) {
321
+ if (_name.length < 3) {
320
322
  DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
321
323
  }
322
- else if (name.length == 4) {
324
+ else if (_name.length == 4) {
323
325
  DESERIALIZE =
324
326
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
325
327
  ` else {\n return false;\n }\n`;
@@ -400,11 +402,12 @@ export default class Transformer extends Transform {
400
402
  }
401
403
  var PropertyFlags;
402
404
  (function (PropertyFlags) {
403
- PropertyFlags[PropertyFlags["Omit"] = 0] = "Omit";
404
- PropertyFlags[PropertyFlags["OmitNull"] = 1] = "OmitNull";
405
- PropertyFlags[PropertyFlags["OmitIf"] = 2] = "OmitIf";
406
- PropertyFlags[PropertyFlags["Alias"] = 3] = "Alias";
407
- PropertyFlags[PropertyFlags["JSON_Raw"] = 4] = "JSON_Raw";
405
+ PropertyFlags[PropertyFlags["Null"] = 0] = "Null";
406
+ PropertyFlags[PropertyFlags["Omit"] = 1] = "Omit";
407
+ PropertyFlags[PropertyFlags["OmitNull"] = 2] = "OmitNull";
408
+ PropertyFlags[PropertyFlags["OmitIf"] = 3] = "OmitIf";
409
+ PropertyFlags[PropertyFlags["Alias"] = 4] = "Alias";
410
+ PropertyFlags[PropertyFlags["JSON_Raw"] = 5] = "JSON_Raw";
408
411
  })(PropertyFlags || (PropertyFlags = {}));
409
412
  class Property {
410
413
  constructor() {
@@ -426,8 +429,14 @@ class Property {
426
429
  if (this.flags.has(PropertyFlags.Omit))
427
430
  return;
428
431
  if (this.flags.has(PropertyFlags.JSON_Raw)) {
429
- this.right_s = "this." + name;
430
- this.right_d = "data.substring(value_start, value_end);";
432
+ if (this.flags.has(PropertyFlags.Null)) {
433
+ this.right_s = "(this." + name + " || \"null\")";
434
+ this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
435
+ }
436
+ else {
437
+ this.right_s = "this." + name;
438
+ this.right_d = "data.substring(value_start, value_end);";
439
+ }
431
440
  }
432
441
  else {
433
442
  this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.9.20",
3
+ "version": "0.9.21",
4
4
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -24,7 +24,7 @@ class JSONTransform extends BaseVisitor {
24
24
  public currentClass!: SchemaData;
25
25
  public sources = new Set<Source>();
26
26
 
27
- visitMethodDeclaration(): void {}
27
+ visitMethodDeclaration(): void { }
28
28
  visitClassDeclaration(node: ClassDeclaration): void {
29
29
  if (!node.decorators?.length) return;
30
30
 
@@ -109,9 +109,9 @@ class JSONTransform extends BaseVisitor {
109
109
  if (!member.type) {
110
110
  throw new Error(
111
111
  "Fields must be strongly typed! Found " +
112
- toString(member) +
113
- " at " +
114
- node.range.source.normalizedPath,
112
+ toString(member) +
113
+ " at " +
114
+ node.range.source.normalizedPath,
115
115
  );
116
116
  }
117
117
  const type = toString(member.type!);
@@ -128,10 +128,14 @@ class JSONTransform extends BaseVisitor {
128
128
  mem.value = value;
129
129
  mem.node = member;
130
130
 
131
- if (type == "JSON.Raw") {
131
+ if (type.includes("JSON.Raw")) {
132
132
  mem.flags.set(PropertyFlags.JSON_Raw, []);
133
133
  }
134
134
 
135
+ if (member.type.isNullable) {
136
+ mem.flags.set(PropertyFlags.Null, []);
137
+ }
138
+
135
139
  if (member.decorators) {
136
140
  for (const decorator of member.decorators) {
137
141
  const decoratorName = (decorator.name as IdentifierExpression).text;
@@ -143,7 +147,7 @@ class JSONTransform extends BaseVisitor {
143
147
  if (!args.length)
144
148
  throw new Error(
145
149
  "Expected 1 argument but got zero at @alias in " +
146
- node.range.source.normalizedPath,
150
+ node.range.source.normalizedPath,
147
151
  );
148
152
  mem.alias = args[0]!;
149
153
  mem.flags.set(PropertyFlags.Alias, args);
@@ -157,7 +161,7 @@ class JSONTransform extends BaseVisitor {
157
161
  if (!decorator.args?.length)
158
162
  throw new Error(
159
163
  "Expected 1 argument but got zero at @omitif in " +
160
- node.range.source.normalizedPath,
164
+ node.range.source.normalizedPath,
161
165
  );
162
166
  mem.flags.set(PropertyFlags.OmitIf, args);
163
167
  break;
@@ -268,36 +272,35 @@ class JSONTransform extends BaseVisitor {
268
272
  SERIALIZE_PRETTY +=
269
273
  "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
270
274
  } else {
271
- SERIALIZE_RAW += "`;\n};";
272
- SERIALIZE_PRETTY += "`;\n};";
275
+ SERIALIZE_RAW += "}`;\n return out;\n}";
276
+ SERIALIZE_PRETTY += "}`;\n return out;\n}";
273
277
  }
274
278
 
275
279
  INITIALIZE += " return this;\n}";
276
280
 
277
281
  const sortedMembers: Property[][] = [];
278
282
  const _sorted = schema.members.sort(
279
- (a, b) => a.name.length - b.name.length,
283
+ (a, b) => (a.alias?.length! || a.name.length) - (b.alias?.length! || b.name.length),
280
284
  );
281
- let len = 0;
282
- let offset = 0;
283
- sortedMembers.push([_sorted[0]!]);
284
- len = _sorted[0]?.name.length!;
285
- for (let i = 1; i < _sorted.length; i++) {
285
+ let len = -1;
286
+ let offset = -1;
287
+ for (let i = 0; i < _sorted.length; i++) {
286
288
  const member = _sorted[i]!;
287
- if (member.alias?.length || member.name.length > len) {
289
+ const _name = member.alias || member.name;
290
+ if (_name.length === len) {
291
+ sortedMembers[offset]?.push(member);
292
+ } else {
288
293
  sortedMembers.push([member]);
289
- len = member.alias?.length || member.name.length;
294
+ len = _name.length;
290
295
  offset++;
291
- } else {
292
- sortedMembers[offset]!.push(member);
293
296
  }
294
297
  }
295
298
 
296
299
  let first = true;
297
300
  for (const memberSet of sortedMembers) {
298
301
  const firstMember = memberSet[0]!;
299
- const name = encodeKey(firstMember.alias || firstMember.name);
300
- if (name.length === 1) {
302
+ const _name = encodeKey(firstMember.alias || firstMember.name);
303
+ if (_name.length === 1) {
301
304
  if (first) {
302
305
  DESERIALIZE +=
303
306
  " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
@@ -306,7 +309,7 @@ class JSONTransform extends BaseVisitor {
306
309
  DESERIALIZE +=
307
310
  "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
308
311
  }
309
- } else if (name.length === 2) {
312
+ } else if (_name.length === 2) {
310
313
  if (first) {
311
314
  DESERIALIZE +=
312
315
  " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
@@ -315,7 +318,7 @@ class JSONTransform extends BaseVisitor {
315
318
  DESERIALIZE +=
316
319
  "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
317
320
  }
318
- } else if (name.length === 4) {
321
+ } else if (_name.length === 4) {
319
322
  if (first) {
320
323
  DESERIALIZE +=
321
324
  " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
@@ -326,44 +329,44 @@ class JSONTransform extends BaseVisitor {
326
329
  }
327
330
  } else {
328
331
  if (first) {
329
- DESERIALIZE += " if (" + name.length + " === len) {\n";
332
+ DESERIALIZE += " if (" + _name.length + " === len) {\n";
330
333
  first = false;
331
334
  } else {
332
- DESERIALIZE += "else if (" + name.length + " === len) {\n";
335
+ DESERIALIZE += "else if (" + _name.length + " === len) {\n";
333
336
  }
334
337
  }
335
338
  let f = true;
336
339
  for (let i = 0; i < memberSet.length; i++) {
337
340
  const member = memberSet[i]!;
338
341
  if (!member.deserialize) continue;
339
- const name = encodeKey(member.alias || member.name);
340
- if (name.length === 1) {
341
- DESERIALIZE += ` case ${name.charCodeAt(0)}: {\n ${member.deserialize}\n return true;\n }\n`;
342
- } else if (name.length === 2) {
343
- DESERIALIZE += ` case ${charCodeAt32(name, 0)}: {\n ${member.deserialize}\n return true;\n }\n`;
344
- } else if (name.length === 4) {
342
+ const _name = encodeKey(member.alias || member.name);
343
+ if (_name.length === 1) {
344
+ DESERIALIZE += ` case ${_name.charCodeAt(0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
345
+ } else if (_name.length === 2) {
346
+ DESERIALIZE += ` case ${charCodeAt32(_name, 0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
347
+ } else if (_name.length === 4) {
345
348
  if (f) {
346
349
  f = false;
347
- DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
350
+ DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
348
351
  } else {
349
352
  DESERIALIZE =
350
353
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
351
- `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
354
+ `else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
352
355
  }
353
356
  } else {
354
357
  if (f) {
355
358
  f = false;
356
- DESERIALIZE += ` if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
359
+ DESERIALIZE += ` if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
357
360
  } else {
358
361
  DESERIALIZE =
359
362
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
360
- ` else if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
363
+ ` else if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
361
364
  }
362
365
  }
363
366
  }
364
- if (name.length < 3) {
367
+ if (_name.length < 3) {
365
368
  DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
366
- } else if (name.length == 4) {
369
+ } else if (_name.length == 4) {
367
370
  DESERIALIZE =
368
371
  DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
369
372
  ` else {\n return false;\n }\n`;
@@ -456,6 +459,7 @@ export default class Transformer extends Transform {
456
459
  }
457
460
 
458
461
  enum PropertyFlags {
462
+ Null,
459
463
  Omit,
460
464
  OmitNull,
461
465
  OmitIf,
@@ -489,8 +493,13 @@ class Property {
489
493
  if (this.flags.has(PropertyFlags.Omit)) return;
490
494
 
491
495
  if (this.flags.has(PropertyFlags.JSON_Raw)) {
492
- this.right_s = "this." + name;
493
- this.right_d = "data.substring(value_start, value_end);";
496
+ if (this.flags.has(PropertyFlags.Null)) {
497
+ this.right_s = "(this." + name + " || \"null\")";
498
+ this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
499
+ } else {
500
+ this.right_s = "this." + name;
501
+ this.right_d = "data.substring(value_start, value_end);";
502
+ }
494
503
  } else {
495
504
  this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
496
505
  this.right_d =