json-as 1.1.6 → 1.1.8

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,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-05-27 - 1.1.8
4
+
5
+ - feat: add support for calling `JSON.stringify/JSON.parse` methods inside of custom serializers, but not yet deserializers
6
+
7
+ ## 2025-05-27 - 1.1.7
8
+
9
+ - fix: bad boolean logic to decide whether to add 2nd break statement
10
+
3
11
  ## 2025-05-23 - 1.1.6
4
12
 
5
13
  - fix: null and boolean fields would miscalculate offsets when deserializing
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.1.6
9
+ AssemblyScript - v1.1.8
10
10
  </pre>
11
11
  </h6>
12
12
 
package/assembly/index.ts CHANGED
@@ -424,7 +424,7 @@ export namespace JSON {
424
424
  // @ts-ignore: type
425
425
  private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
426
426
 
427
- constructor() {}
427
+ constructor() { }
428
428
 
429
429
  // @ts-ignore: decorator
430
430
  @inline get size(): i32 {
@@ -515,6 +515,12 @@ export namespace JSON {
515
515
  }
516
516
  }
517
517
 
518
+ /**
519
+ * Serializes JSON data but writes directly to the buffer.
520
+ * Should only be used if you know what you are doing.
521
+ * @param src - T
522
+ * @returns void
523
+ */
518
524
  export function __serialize<T>(src: T): void {
519
525
  if (isBoolean<T>()) {
520
526
  serializeBool(src as bool);
@@ -565,6 +571,14 @@ export namespace JSON {
565
571
  }
566
572
  }
567
573
 
574
+ /**
575
+ * Deserializes JSON data directly from the buffer.
576
+ * Should only be used if you know what you are doing.
577
+ * @param srcStart - usize
578
+ * @param srcEnd - usize
579
+ * @param dst - usize
580
+ * @returns void
581
+ */
568
582
  export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
569
583
  if (isBoolean<T>()) {
570
584
  // @ts-ignore: type
@@ -612,7 +626,7 @@ export namespace JSON {
612
626
  }
613
627
  throw new Error(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`);
614
628
  }
615
- export namespace Util {
629
+ namespace Util {
616
630
  // @ts-ignore: decorator
617
631
  @inline export function isSpace(code: u16): boolean {
618
632
  return code == 0x20 || code - 9 <= 4;
@@ -625,6 +639,127 @@ export namespace JSON {
625
639
  return changetype<string>(out);
626
640
  }
627
641
  }
642
+ /**
643
+ * Methods for use when using JSON methods inside another JSON method or custom serializer/deserializer.
644
+ */
645
+ export namespace internal {
646
+ /**
647
+ * Serializes JSON data. Don't use this directly, use `JSON.stringify` instead.
648
+ * @param data - T
649
+ * @param out - string | null
650
+ * @returns - string
651
+ */
652
+ // @ts-ignore: inline
653
+ @inline export function stringify<T>(data: T, out: string | null = null): string {
654
+ if (isBoolean<T>()) {
655
+ if (out) {
656
+ if (<bool>data == true) {
657
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
658
+ store<u64>(changetype<usize>(out), 28429475166421108);
659
+ } else {
660
+ out = changetype<string>(__renew(changetype<usize>(out), 10));
661
+ store<u64>(changetype<usize>(out), 32370086184550502);
662
+ store<u16>(changetype<usize>(out), 101, 8);
663
+ }
664
+ return out;
665
+ }
666
+ return data ? "true" : "false";
667
+ } else if (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && data == 0) {
668
+ if (out) {
669
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
670
+ store<u64>(changetype<usize>(out), 30399761348886638);
671
+ return out;
672
+ }
673
+ return NULL_WORD;
674
+ } else if (isInteger<T>(data)) {
675
+ if (out) {
676
+ out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
677
+
678
+ // @ts-ignore
679
+ const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
680
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
681
+ }
682
+ return data.toString();
683
+ } else if (isFloat<T>(data)) {
684
+ if (out) {
685
+ out = changetype<string>(__renew(changetype<usize>(out), 64));
686
+
687
+ // @ts-ignore
688
+ const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
689
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
690
+ }
691
+ return data.toString();
692
+ // @ts-ignore: Function is generated by transform
693
+ } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
694
+ if (out) {
695
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
696
+ store<u64>(changetype<usize>(out), 30399761348886638);
697
+ return out;
698
+ }
699
+ return NULL_WORD;
700
+ // @ts-ignore
701
+ } else if (isString<nonnull<T>>()) {
702
+ // if (out) {
703
+ // out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
704
+ // // const oldSize = bs.byteLength;
705
+ // const oldBuf = bs.buffer;
706
+ // const newSize = bytes(data) + 4;
707
+ // const newBuf = __new(newSize, idof<string>());
708
+ // bs.setBuffer(newBuf);
709
+ // serializeString(changetype<string>(data));
710
+ // bs.setBuffer(oldBuf);
711
+ // return changetype<string>(newBuf);
712
+ // }
713
+ // if (ASC_FEATURE_SIMD) {
714
+ // serializeString_SIMD(data as string);
715
+ // } else {
716
+ bs.saveState();
717
+ serializeString(data as string);
718
+ // }
719
+ return bs.cpyOut<string>();
720
+ // @ts-ignore: Supplied by transform
721
+ } else if (isDefined(data.__SERIALIZE)) {
722
+ bs.saveState();
723
+ // @ts-ignore
724
+ inline.always(data.__SERIALIZE(changetype<usize>(data)));
725
+ return bs.cpyOut<string>();
726
+ // @ts-ignore: Supplied by transform
727
+ } else if (data instanceof Date) {
728
+ out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
729
+
730
+ store<u16>(changetype<usize>(out), QUOTE);
731
+ memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
732
+ store<u16>(changetype<usize>(out), QUOTE, 50);
733
+ return changetype<string>(out);
734
+ } else if (data instanceof Array) {
735
+ bs.saveState();
736
+ // @ts-ignore
737
+ inline.always(serializeArray(changetype<nonnull<T>>(data)));
738
+ return bs.cpyOut<string>();
739
+ } else if (data instanceof Map) {
740
+ bs.saveState();
741
+ // @ts-ignore
742
+ inline.always(serializeMap(changetype<nonnull<T>>(data)));
743
+ return bs.cpyOut<string>();
744
+ } else if (data instanceof JSON.Raw) {
745
+ bs.saveState();
746
+ serializeRaw(data);
747
+ return bs.cpyOut<string>();
748
+ } else if (data instanceof JSON.Value) {
749
+ bs.saveState();
750
+ inline.always(serializeArbitrary(data));
751
+ return bs.cpyOut<string>();
752
+ } else if (data instanceof JSON.Obj) {
753
+ bs.saveState();
754
+ inline.always(serializeObject(data));
755
+ return bs.cpyOut<string>();
756
+ } else if (data instanceof JSON.Box) {
757
+ return JSON.internal.stringify(data.value);
758
+ } else {
759
+ throw new Error(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
760
+ }
761
+ }
762
+ }
628
763
  }
629
764
 
630
765
  // @ts-ignore: decorator
package/assembly/test.ts CHANGED
@@ -1,218 +1,292 @@
1
1
  import { JSON } from ".";
2
2
  import { bytes } from "./util";
3
3
 
4
- @json
5
- class Obj {
6
- public a: string = "hello";
7
- public b: string = "world";
8
- public c: string = '"\t\f\u0000\u0001';
9
- }
4
+ // @json
5
+ // class Obj {
6
+ // public a: string = "hello";
7
+ // public b: string = "world";
8
+ // public c: string = '"\t\f\u0000\u0001';
9
+ // }
10
+
11
+ // @json
12
+ // class Vec3 {
13
+ // x: f32 = 0.0;
14
+ // y: f32 = 0.0;
15
+ // z: f32 = 0.0;
16
+ // }
17
+
18
+ // @json
19
+ // class Player {
20
+ // @alias("first name")
21
+ // firstName!: string;
22
+ // lastName!: string;
23
+ // lastActive!: i32[];
24
+ // // Drop in a code block, function, or expression that evaluates to a boolean
25
+ // @omitif((self: Player) => self.age < 18)
26
+ // age!: i32;
27
+
28
+ // @omitnull()
29
+ // pos!: Vec3 | null;
30
+ // isVerified!: boolean;
31
+ // }
32
+
33
+ // @json
34
+ // class Point { }
35
+
36
+ // @json
37
+ // class NewPoint {
38
+ // x: f64 = 0.0;
39
+ // y: f64 = 0.0;
40
+ // constructor(x: f64, y: f64) {
41
+ // this.x = x;
42
+ // this.y = y;
43
+ // }
10
44
 
11
- @json
12
- class Vec3 {
13
- x: f32 = 0.0;
14
- y: f32 = 0.0;
15
- z: f32 = 0.0;
16
- }
45
+ // @serializer
46
+ // serializer(self: NewPoint): string {
47
+ // return `x=${self.x},y=${self.y}`;
48
+ // }
17
49
 
18
- @json
19
- class Player {
20
- @alias("first name")
21
- firstName!: string;
22
- lastName!: string;
23
- lastActive!: i32[];
24
- // Drop in a code block, function, or expression that evaluates to a boolean
25
- @omitif((self: Player) => self.age < 18)
26
- age!: i32;
27
-
28
- @omitnull()
29
- pos!: Vec3 | null;
30
- isVerified!: boolean;
31
- }
50
+ // @deserializer
51
+ // deserializer(data: string): NewPoint {
52
+ // const dataSize = bytes(data);
32
53
 
33
- @json
34
- class Point {}
54
+ // const c = data.indexOf(",");
55
+ // const x = data.slice(2, c);
56
+ // const y = data.slice(c + 3);
35
57
 
36
- @json
37
- class NewPoint {
38
- x: f64 = 0.0;
39
- y: f64 = 0.0;
40
- constructor(x: f64, y: f64) {
41
- this.x = x;
42
- this.y = y;
43
- }
58
+ // return new NewPoint(f64.parse(x), f64.parse(y));
59
+ // }
60
+ // }
44
61
 
45
- @serializer
46
- serializer(self: NewPoint): string {
47
- return `x=${self.x},y=${self.y}`;
48
- }
62
+ // @json
63
+ // class InnerObj<T> {
64
+ // obj: T = instantiate<T>();
65
+ // }
49
66
 
50
- @deserializer
51
- deserializer(data: string): NewPoint {
52
- const dataSize = bytes(data);
67
+ // @json
68
+ // class ObjWithBracketString {
69
+ // data: string = "";
70
+ // }
53
71
 
54
- const c = data.indexOf(",");
55
- const x = data.slice(2, c);
56
- const y = data.slice(c + 3);
72
+ // const player: Player = {
73
+ // firstName: "Jairus",
74
+ // lastName: "Tanaka",
75
+ // lastActive: [2, 7, 2025],
76
+ // age: 18,
77
+ // pos: {
78
+ // x: 3.4,
79
+ // y: 1.2,
80
+ // z: 8.3,
81
+ // },
82
+ // isVerified: true,
83
+ // };
57
84
 
58
- return new NewPoint(f64.parse(x), f64.parse(y));
59
- }
60
- }
85
+ // const a1 = JSON.stringify("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u000f\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f");
86
+ // // console.log("Bytes " + bytes(a1).toString());
87
+ // console.log("a1: " + a1);
61
88
 
62
- @json
63
- class InnerObj<T> {
64
- obj: T = instantiate<T>();
65
- }
89
+ // const obj = new Obj();
90
+ // const a2 = JSON.stringify(obj);
91
+ // // console.log("Bytes " + bytes(a2).toString());
92
+ // console.log("a2: " + a2);
66
93
 
67
- @json
68
- class ObjWithBracketString {
69
- data: string = "";
70
- }
94
+ // const a3 = JSON.stringify(player);
95
+ // // console.log("Bytes " + bytes(a3).toString());
96
+ // console.log("a3: " + a3);
71
97
 
72
- const player: Player = {
73
- firstName: "Jairus",
74
- lastName: "Tanaka",
75
- lastActive: [2, 7, 2025],
76
- age: 18,
77
- pos: {
78
- x: 3.4,
79
- y: 1.2,
80
- z: 8.3,
81
- },
82
- isVerified: true,
83
- };
98
+ // const a4 = new JSON.Obj();
84
99
 
85
- const a1 = JSON.stringify("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u000f\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f");
86
- // console.log("Bytes " + bytes(a1).toString());
87
- console.log("a1: " + a1);
100
+ // a4.set("x", 1.5);
101
+ // a4.set("y", 5.4);
102
+ // a4.set("z", 9.8);
103
+ // a4.set("obj", obj);
104
+ // a4.set<boolean>("bool", false);
105
+
106
+ // console.log("a4: " + JSON.stringify(a4));
107
+
108
+ // const a5 = JSON.parse<JSON.Obj>('{"foo":"bar"}');
88
109
 
89
- const obj = new Obj();
90
- const a2 = JSON.stringify(obj);
91
- // console.log("Bytes " + bytes(a2).toString());
92
- console.log("a2: " + a2);
110
+ // console.log("a5: " + JSON.stringify(a5));
93
111
 
94
- const a3 = JSON.stringify(player);
95
- // console.log("Bytes " + bytes(a3).toString());
96
- console.log("a3: " + a3);
112
+ // const a6 = JSON.parse<JSON.Obj>('{"x":1.5,"y":5.4,"z":9.8,"obj":{"foo":"bar"}}');
97
113
 
98
- const a4 = new JSON.Obj();
114
+ // console.log("a6: " + JSON.stringify(a6));
99
115
 
100
- a4.set("x", 1.5);
101
- a4.set("y", 5.4);
102
- a4.set("z", 9.8);
103
- a4.set("obj", obj);
104
- a4.set<boolean>("bool", false);
116
+ // const a7 = JSON.parse<JSON.Value[]>('["string",true,3.14,{"x":1.0,"y":2.0,"z":3.0},[1,2,3,true]]');
105
117
 
106
- console.log("a4: " + JSON.stringify(a4));
118
+ // console.log("a7: " + JSON.stringify(a7));
107
119
 
108
- const a5 = JSON.parse<JSON.Obj>('{"foo":"bar"}');
120
+ // const a8 = JSON.stringify(["hello", JSON.stringify("world"), "working?"]);
109
121
 
110
- console.log("a5: " + JSON.stringify(a5));
122
+ // console.log("a8: " + a8);
111
123
 
112
- const a6 = JSON.parse<JSON.Obj>('{"x":1.5,"y":5.4,"z":9.8,"obj":{"foo":"bar"}}');
124
+ // const a9 = JSON.stringify<JSON.Raw>(JSON.Raw.from('"hello world"'));
113
125
 
114
- console.log("a6: " + JSON.stringify(a6));
126
+ // console.log("a9: " + a9);
115
127
 
116
- const a7 = JSON.parse<JSON.Value[]>('["string",true,3.14,{"x":1.0,"y":2.0,"z":3.0},[1,2,3,true]]');
128
+ // const m10 = new Map<string, JSON.Raw>();
129
+ // m10.set("hello", new JSON.Raw('"world"'));
130
+ // m10.set("pos", new JSON.Raw('{"x":1.0,"y":2.0,"z":3.0}'));
117
131
 
118
- console.log("a7: " + JSON.stringify(a7));
132
+ // const a10 = JSON.stringify(m10);
119
133
 
120
- const a8 = JSON.stringify(["hello", JSON.stringify("world"), "working?"]);
134
+ // console.log("a10: " + a10);
121
135
 
122
- console.log("a8: " + a8);
136
+ // const a11 = JSON.parse<JSON.Obj>(' { "x" : 3.4 , "y" : 1.2 , "z" : 8.3 } ');
123
137
 
124
- const a9 = JSON.stringify<JSON.Raw>(JSON.Raw.from('"hello world"'));
138
+ // console.log("a11: " + JSON.stringify(a11));
125
139
 
126
- console.log("a9: " + a9);
140
+ // const a12 = JSON.parse<InnerObj<ObjWithBracketString>>('{"obj":{"data":"hello} world"}}');
127
141
 
128
- const m10 = new Map<string, JSON.Raw>();
129
- m10.set("hello", new JSON.Raw('"world"'));
130
- m10.set("pos", new JSON.Raw('{"x":1.0,"y":2.0,"z":3.0}'));
142
+ // console.log("a12: " + JSON.stringify(a12));
131
143
 
132
- const a10 = JSON.stringify(m10);
144
+ // const a13 = JSON.stringify<JSON.Obj>(new JSON.Obj());
133
145
 
134
- console.log("a10: " + a10);
146
+ // console.log("a13: " + a13);
135
147
 
136
- const a11 = JSON.parse<JSON.Obj>(' { "x" : 3.4 , "y" : 1.2 , "z" : 8.3 } ');
148
+ // const a14 = JSON.stringify(new Point());
149
+ // console.log("a14: " + a14);
137
150
 
138
- console.log("a11: " + JSON.stringify(a11));
151
+ // const a15 = JSON.parse<Point>(a14);
152
+ // console.log("a15: " + JSON.stringify(a15));
139
153
 
140
- const a12 = JSON.parse<InnerObj<ObjWithBracketString>>('{"obj":{"data":"hello} world"}}');
154
+ // const a16 = JSON.stringify(new NewPoint(1.0, 2.0));
155
+ // console.log("a16: " + a16);
141
156
 
142
- console.log("a12: " + JSON.stringify(a12));
157
+ // const a17 = JSON.parse<NewPoint>(a16);
158
+ // console.log("a17: " + JSON.stringify(a17));
143
159
 
144
- const a13 = JSON.stringify<JSON.Obj>(new JSON.Obj());
160
+ // const a18 = JSON.parse<JSON.Obj[]>('[{"x":1.0,"y":2.0,"z":3.0},{"x":4.0,"y":5.0,"z":6.0},{"x":7.0,"y":8.0,"z":9.0}]');
161
+ // console.log("a18: " + JSON.stringify(a18));
145
162
 
146
- console.log("a13: " + a13);
163
+ // const a19 = JSON.stringify<JSON.Obj[]>(a18);
164
+ // console.log("a19: " + a19);
147
165
 
148
- const a14 = JSON.stringify(new Point());
149
- console.log("a14: " + a14);
166
+ // const a20 = JSON.parse<JSON.Box<f64>[]>("[1.3,4.7,9.5]");
167
+ // console.log("a20: " + JSON.stringify(a20));
150
168
 
151
- const a15 = JSON.parse<Point>(a14);
152
- console.log("a15: " + JSON.stringify(a15));
169
+ // const a21 = JSON.stringify<JSON.Box<f64>[]>(a20);
170
+ // console.log("a21: " + a21);
153
171
 
154
- const a16 = JSON.stringify(new NewPoint(1.0, 2.0));
155
- console.log("a16: " + a16);
172
+ // const a22 = JSON.parse<Foo>('{"id":"0xb8","firstName":"Jairus","lastName":"Tanaka"}');
173
+ // console.log("a22: " + JSON.stringify(a22));
156
174
 
157
- const a17 = JSON.parse<NewPoint>(a16);
158
- console.log("a17: " + JSON.stringify(a17));
159
175
 
160
- const a18 = JSON.parse<JSON.Obj[]>('[{"x":1.0,"y":2.0,"z":3.0},{"x":4.0,"y":5.0,"z":6.0},{"x":7.0,"y":8.0,"z":9.0}]');
161
- console.log("a18: " + JSON.stringify(a18));
176
+ // @json
177
+ // class Foo {
178
+ // id: string = "";
179
+ // firstName: string = "";
180
+ // lastName: string = "";
181
+ // }
162
182
 
163
- const a19 = JSON.stringify<JSON.Obj[]>(a18);
164
- console.log("a19: " + a19);
183
+ // @json
184
+ // class SrvInfo {
185
+ // accessUrl: string = "https://example.com";
186
+ // cardTypes: i32[] = [1, 2, 3];
187
+ // customService: string = "Contact us at support@example.com";
188
+ // invoiceApplicationStatus: i32 = 1;
189
+ // isCertification: bool = true;
190
+ // isOnlineRecharge: bool = false;
191
+ // loginTypes: i32[] = [0, 1]; // e.g. 0 = password, 1 = OTP
192
+ // record: string = "ICP 12345678";
193
+ // regCompanyAudit: i32 = 2;
194
+ // regCompanyPipeline: i32[] = [101, 102, 103];
195
+ // regPwdLimit: i32 = 8; // min password length
196
+ // serverTime: i64 = 1650000000000; // dummy timestamp
197
+ // srvDescription: string = "A demo service for handling customer operations.";
198
+ // srvHiddenMenu: string[] = ["admin", "beta"];
199
+ // srvHost: string = "srv.example.com";
200
+ // srvId: i32 = 999;
201
+ // srvKeywords: string[] = ["finance", "payments", "online"];
202
+ // srvLogoImgUrl: string = "https://example.com/logo.png";
203
+ // srvName: string = "ExampleService";
204
+ // srvPageId: i32 = 5;
205
+ // thirdAuthUrl: string = "https://auth.example.com";
206
+ // userCenterStyle: i32 = 1; // e.g. 1 = modern, 0 = legacy
207
+ // }
165
208
 
166
- const a20 = JSON.parse<JSON.Box<f64>[]>("[1.3,4.7,9.5]");
167
- console.log("a20: " + JSON.stringify(a20));
209
+ // const a23 = JSON.stringify(new SrvInfo());
210
+ // console.log("a23: " + a23);
168
211
 
169
- const a21 = JSON.stringify<JSON.Box<f64>[]>(a20);
170
- console.log("a21: " + a21);
212
+ // const a24 = '{"accessUrl":"https://example.com","cardTypes":[1,2,3],"customService":"Contact us at support@example.com","invoiceApplicationStatus":1,"isCertification":true,"isOnlineRecharge":false,"loginTypes":[0,1],"record":"ICP 12345678","regCompanyAudit":2,"regCompanyPipeline":[101,102,103],"regPwdLimit":8,"serverTime":1650000000000,"srvDescription":"A demo service for handling customer operations.","srvHiddenMenu":["admin","beta"],"srvHost":"srv.example.com","srvId":999,"srvKeywords":["finance","payments","online"],"srvLogoImgUrl":"https://example.com/logo.png","srvName":"ExampleService","srvPageId":5,"thirdAuthUrl":"https://auth.example.com","userCenterStyle":1}';
213
+ // console.log("a25: " + (a24 == a23).toString());
171
214
 
172
- const a22 = JSON.parse<Foo>('{"id":"0xb8","firstName":"Jairus","lastName":"Tanaka"}');
173
- console.log("a22: " + JSON.stringify(a22));
215
+ // const a26 = JSON.parse<SrvInfo>(a23);
216
+ // console.log("a26: " + JSON.stringify(a26));
174
217
 
218
+ // console.log("a27: " + (JSON.stringify(a26) == a23).toString())
219
+ import {
220
+ bs
221
+ } from "../lib/as-bs"
175
222
 
176
223
  @json
177
- class Foo {
178
- id: string = "";
179
- firstName: string = "";
180
- lastName: string = "";
224
+ class GenericEnum<T> {
225
+ private tag: string = ""
226
+ private value: T | null = null
227
+
228
+ constructor() {
229
+ this.tag = ""
230
+ this.value = null
231
+ }
232
+
233
+ static create<T>(tag: string, value: T): GenericEnum<T> {
234
+ const item = new GenericEnum<T>()
235
+ item.tag = tag
236
+ item.value = value
237
+ return item
238
+ }
239
+
240
+ getTag(): string {
241
+ return this.tag
242
+ }
243
+
244
+ getValue(): T | null {
245
+ return this.value
246
+ }
247
+ @serializer
248
+ serialize<T>(self: GenericEnum<T>): string {
249
+ const tagJson = JSON.stringify(self.tag);
250
+ const valueJson = JSON.stringify(self.value);
251
+ return `{${tagJson}:${valueJson}}`
252
+ }
253
+ @deserializer
254
+ deserialize(data: string): GenericEnum<T> {
255
+ const parsed = JSON.parse<Map<string, JSON.Raw>>(data);
256
+ const result = new GenericEnum<T>();
257
+
258
+ const keys = parsed.keys();
259
+ const values = parsed.values();
260
+
261
+ result.tag = keys[0];
262
+ result.value = JSON.parse<T>(values[0].data);
263
+
264
+ return result;
265
+ }
181
266
  }
182
267
 
183
268
  @json
184
- class SrvInfo {
185
- accessUrl: string = "https://example.com";
186
- cardTypes: i32[] = [1, 2, 3];
187
- customService: string = "Contact us at support@example.com";
188
- invoiceApplicationStatus: i32 = 1;
189
- isCertification: bool = true;
190
- isOnlineRecharge: bool = false;
191
- loginTypes: i32[] = [0, 1]; // e.g. 0 = password, 1 = OTP
192
- record: string = "ICP 12345678";
193
- regCompanyAudit: i32 = 2;
194
- regCompanyPipeline: i32[] = [101, 102, 103];
195
- regPwdLimit: i32 = 8; // min password length
196
- serverTime: i64 = 1650000000000; // dummy timestamp
197
- srvDescription: string = "A demo service for handling customer operations.";
198
- srvHiddenMenu: string[] = ["admin", "beta"];
199
- srvHost: string = "srv.example.com";
200
- srvId: i32 = 999;
201
- srvKeywords: string[] = ["finance", "payments", "online"];
202
- srvLogoImgUrl: string = "https://example.com/logo.png";
203
- srvName: string = "ExampleService";
204
- srvPageId: i32 = 5;
205
- thirdAuthUrl: string = "https://auth.example.com";
206
- userCenterStyle: i32 = 1; // e.g. 1 = modern, 0 = legacy
269
+ class Node<T> {
270
+ name: string
271
+ id: u32
272
+ data: T
273
+
274
+ constructor() {
275
+ this.name = ""
276
+ this.id = 0
277
+ this.data = changetype<T>(0);
278
+ }
207
279
  }
208
280
 
209
- const a23 = JSON.stringify(new SrvInfo());
210
- console.log("a23: " + a23);
281
+ const enumValue = GenericEnum.create<string>("success", "Hello World")
211
282
 
212
- const a24 = '{"accessUrl":"https://example.com","cardTypes":[1,2,3],"customService":"Contact us at support@example.com","invoiceApplicationStatus":1,"isCertification":true,"isOnlineRecharge":false,"loginTypes":[0,1],"record":"ICP 12345678","regCompanyAudit":2,"regCompanyPipeline":[101,102,103],"regPwdLimit":8,"serverTime":1650000000000,"srvDescription":"A demo service for handling customer operations.","srvHiddenMenu":["admin","beta"],"srvHost":"srv.example.com","srvId":999,"srvKeywords":["finance","payments","online"],"srvLogoImgUrl":"https://example.com/logo.png","srvName":"ExampleService","srvPageId":5,"thirdAuthUrl":"https://auth.example.com","userCenterStyle":1}';
213
- console.log("a25: " + (a24 == a23).toString());
283
+ const node = new Node<GenericEnum<string>>();
284
+ node.name = "test-node";
285
+ node.id = 42;
286
+ node.data = enumValue;
214
287
 
215
- const a26 = JSON.parse<SrvInfo>(a23);
216
- console.log("a26: " + JSON.stringify(a26));
288
+ const serialized = JSON.stringify(node);
289
+ console.log("Serialized Node: " + serialized);
217
290
 
218
- console.log("a27: " + (JSON.stringify(a26) == a23).toString())
291
+ const deserialized = JSON.parse<JSON.Obj>(serialized)
292
+ console.log("Deserialized Node: " + JSON.stringify(deserialized));