json-as 1.1.14 → 1.1.15-preview.1
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 +9 -0
- package/README.md +19 -1
- package/assembly/__tests__/array.spec.ts +130 -159
- package/assembly/__tests__/generics.spec.ts +32 -23
- package/assembly/__tests__/lib/index.ts +7 -3
- package/assembly/__tests__/resolving.spec.ts +13 -5
- package/assembly/__tests__/staticarray.spec.ts +12 -0
- package/assembly/__tests__/types.spec.ts +3 -2
- package/assembly/deserialize/simple/array/raw.ts +106 -0
- package/assembly/deserialize/simple/array.ts +5 -1
- package/assembly/index.ts +12 -10
- package/assembly/test.ts +7 -1
- package/assembly/types.ts +26 -18
- package/package.json +24 -23
- package/publish.sh +78 -0
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/index.js +26 -50
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/custom.js.map +1 -1
- package/transform/src/builder.ts +1 -1
- package/transform/src/index.ts +258 -297
- package/transform/src/linkers/alias.ts +1 -2
- package/transform/src/linkers/classes.ts +1 -1
- package/transform/src/linkers/custom.ts +26 -26
- package/transform/src/types.ts +1 -1
- package/assembly/test.json.ts +0 -388
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.
|
|
9
|
+
AssemblyScript - v1.1.15-preview.1
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
7
|
+
public foo: T;
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
constructor(foo: T) {
|
|
10
|
+
this.foo = foo;
|
|
11
|
+
}
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
|
|
13
15
|
@json
|
|
14
16
|
class Vec3 {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
public x!: i32;
|
|
18
|
+
public y!: i32;
|
|
19
|
+
public z!: i32;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
describe("Should serialize generics", () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
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
|
|
29
|
+
if (this.left != (isNull(right) ? "null" : right.toString())) {
|
|
30
30
|
console.log(" " + currentDescription + "\n");
|
|
31
31
|
// @ts-ignore
|
|
32
|
-
console.log(" (expected) -> " + (right
|
|
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
|
-
|
|
40
|
+
bar: Bar = new Bar();
|
|
34
41
|
}
|
|
35
42
|
|
|
43
|
+
|
|
36
44
|
@json
|
|
37
45
|
class Bar {
|
|
38
|
-
|
|
46
|
+
baz: string = "buz";
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
describe("Should resolve imported schemas", () => {
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
+
expect(JSON.stringify(alias)).toBe('{"foo":"bar"}');
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
describe("Should deserialize with type aliases", () => {
|
|
25
|
-
|
|
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
|
+
}
|