json-as 0.9.3 → 0.9.5
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 +3 -0
- package/README.md +12 -1
- package/assembly/index.d.ts +6 -0
- package/assembly/serialize/unknown.ts +45 -0
- package/assembly/test.ts +41 -16
- package/package.json +1 -1
- package/transform/lib/index.js +20 -1
- package/transform/package.json +1 -1
- package/transform/src/index.ts +17 -2
package/CHANGELOG
CHANGED
|
@@ -7,5 +7,8 @@ v0.8.6 - Fix. Forgot to stash before publishing. Stash and push what should have
|
|
|
7
7
|
v0.9.0 - BREAKING CHANGE - API changed from JSON.parse(data, defaultValues) to JSON.parse(data). Default Values defaults to true. Large update. Refactor all the code, nullable primitives, rewrite the transform, allow extensibility with @omit keywords, and fix a plethora of bugs
|
|
8
8
|
v0.9.1 - Fix #71
|
|
9
9
|
v0.9.2 - Fix #75 + Build sizes significantly reduced
|
|
10
|
+
v0.9.3 - Fix #76
|
|
11
|
+
v0.9.4 - Fix #77
|
|
12
|
+
v0.9.5 - Fix #46
|
|
10
13
|
|
|
11
14
|
[UNRELEASED] v0.9.x - Port JSON.Value from the `develop` branch to allow for union types, parsing of arbitrary data, and whatever the hell you want.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
██║ ██║███████║ ╚█████╔╝███████║╚██████╔╝██║ ╚████║
|
|
8
8
|
╚═╝ ╚═╝╚══════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
9
9
|
|
|
10
|
-
v0.9.
|
|
10
|
+
v0.9.5
|
|
11
11
|
</pre>
|
|
12
12
|
</h3>
|
|
13
13
|
|
|
@@ -111,6 +111,17 @@ const serialized = JSON.stringify(arr);
|
|
|
111
111
|
const parsed = JSON.parse<Base[]>(serialized);
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
Classes can even have inheritance. Here's a nasty example
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
@json
|
|
118
|
+
class Base {}
|
|
119
|
+
|
|
120
|
+
const serialized = JSON.stringify(arr);
|
|
121
|
+
// [{"x":1.0},{"x":1.0,"y":2.0},{"y":2.0,"x":1.0,"z":3.0}]
|
|
122
|
+
const parsed = JSON.parse<Base[]>(serialized);
|
|
123
|
+
```
|
|
124
|
+
|
|
114
125
|
If you use this project in your codebase, consider dropping a [star](https://github.com/JairusSW/as-json). I would really appreciate it!
|
|
115
126
|
|
|
116
127
|
## Notes
|
package/assembly/index.d.ts
CHANGED
|
@@ -28,3 +28,9 @@ declare function omitif(condition: string): Function;
|
|
|
28
28
|
* Property decorator that allows a field to be omitted when a property is null.
|
|
29
29
|
*/
|
|
30
30
|
declare function omitnull(): Function;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Property decorator that allows a field to be flattened.
|
|
34
|
+
* @param fieldName - Points to the field to flatten. Can use dot-notation here like @omit("foo.identifier.text")
|
|
35
|
+
*/
|
|
36
|
+
declare function flatten(fieldName: string = "value"): Function;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { Sink } from "../src/sink";
|
|
3
|
+
import { __atoi_fast } from "../src/util";
|
|
4
|
+
import { serializeUnknownArray } from "./array/unknown";
|
|
5
|
+
import { serializeBool } from "./bool";
|
|
6
|
+
import { serializeFloat } from "./float";
|
|
7
|
+
import { serializeInteger } from "./integer";
|
|
8
|
+
import { serializeString } from "./string";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Serializes unknown values into their correct serializer and returns the data.
|
|
12
|
+
*
|
|
13
|
+
* @param data - The JSON.Value to be serialized.
|
|
14
|
+
* @returns The serialized result.
|
|
15
|
+
*/
|
|
16
|
+
export function serializeUnknown(data: JSON.Value): string {
|
|
17
|
+
const type = data.type;
|
|
18
|
+
switch (type) {
|
|
19
|
+
case JSON.Types.String: {
|
|
20
|
+
return serializeString(data.get<string>());
|
|
21
|
+
}
|
|
22
|
+
case JSON.Types.Bool: {
|
|
23
|
+
return serializeBool(data.get<bool>());
|
|
24
|
+
}
|
|
25
|
+
case JSON.Types.U8: {
|
|
26
|
+
return serializeInteger(data.get<u8>());
|
|
27
|
+
}
|
|
28
|
+
case JSON.Types.U16: {
|
|
29
|
+
return serializeInteger(data.get<u16>());
|
|
30
|
+
}
|
|
31
|
+
case JSON.Types.U32: {
|
|
32
|
+
return serializeInteger(data.get<u32>());
|
|
33
|
+
}
|
|
34
|
+
case JSON.Types.U64: {
|
|
35
|
+
return serializeInteger(data.get<u64>());
|
|
36
|
+
}
|
|
37
|
+
case JSON.Types.F32: {
|
|
38
|
+
return serializeFloat(data.get<f32>());
|
|
39
|
+
}
|
|
40
|
+
case JSON.Types.F64: {
|
|
41
|
+
return serializeFloat(data.get<f64>());
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return serializeUnknownArray(data.get<JSON.Value[]>());
|
|
45
|
+
}
|
package/assembly/test.ts
CHANGED
|
@@ -1,25 +1,50 @@
|
|
|
1
1
|
import { JSON } from ".";
|
|
2
2
|
|
|
3
|
+
// @json or @serializable work here
|
|
3
4
|
@json
|
|
4
|
-
class
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
class Vec3 {
|
|
6
|
+
x: f32 = 0.0;
|
|
7
|
+
y: f32 = 0.0;
|
|
8
|
+
z: f32 = 0.0;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
class
|
|
11
|
-
|
|
12
|
-
y: f32 = 2.0;
|
|
10
|
+
|
|
11
|
+
class Box<T> {
|
|
12
|
+
value: T;
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
@json
|
|
15
|
-
class
|
|
16
|
-
|
|
16
|
+
class Player {
|
|
17
|
+
@alias("first name")
|
|
18
|
+
firstName!: string;
|
|
19
|
+
lastName!: string;
|
|
20
|
+
lastActive!: i32[];
|
|
21
|
+
// Drop in a code block, function, or expression that evaluates to a boolean
|
|
22
|
+
@omitif("this.age < 18")
|
|
23
|
+
age!: i32;
|
|
24
|
+
@omitnull()
|
|
25
|
+
pos!: Vec3 | null;
|
|
26
|
+
isVerified!: boolean;
|
|
27
|
+
@flatten("value")
|
|
28
|
+
box: Box<i32> | null;
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
const player: Player = {
|
|
32
|
+
firstName: "Emmet",
|
|
33
|
+
lastName: "West",
|
|
34
|
+
lastActive: [8, 27, 2022],
|
|
35
|
+
age: 23,
|
|
36
|
+
pos: {
|
|
37
|
+
x: 3.4,
|
|
38
|
+
y: 1.2,
|
|
39
|
+
z: 8.3
|
|
40
|
+
},
|
|
41
|
+
isVerified: true,
|
|
42
|
+
box: null
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const stringified = JSON.stringify<Player>(player);
|
|
46
|
+
|
|
47
|
+
const parsed = JSON.parse<Player>(stringified);
|
|
24
48
|
|
|
25
|
-
console.log(
|
|
49
|
+
console.log("Stringified: " + stringified);
|
|
50
|
+
console.log("Parsed: " + JSON.stringify(parsed));
|
package/package.json
CHANGED
package/transform/lib/index.js
CHANGED
|
@@ -102,6 +102,12 @@ class JSONTransform extends BaseVisitor {
|
|
|
102
102
|
mem.args?.push(decorator.args[0].value);
|
|
103
103
|
mem.flag = PropertyFlags.OmitIf;
|
|
104
104
|
}
|
|
105
|
+
else if (decorator.name.text == "flatten") {
|
|
106
|
+
if (!decorator.args?.length)
|
|
107
|
+
throw new Error("Expected 1 argument but got zero at @flatten in " + node.range.source.normalizedPath);
|
|
108
|
+
mem.flag = PropertyFlags.Flatten;
|
|
109
|
+
mem.args = [decorator.args[0].value];
|
|
110
|
+
}
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
113
|
if (mem.flag === PropertyFlags.Alias) {
|
|
@@ -124,9 +130,21 @@ class JSONTransform extends BaseVisitor {
|
|
|
124
130
|
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));";
|
|
125
131
|
mem.name = name.text;
|
|
126
132
|
}
|
|
133
|
+
else if (mem.flag == PropertyFlags.Flatten) {
|
|
134
|
+
const nullable = mem.node.type.isNullable;
|
|
135
|
+
if (nullable) {
|
|
136
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${this." + name.text + " ? __SERIALIZE(changetype<nonnull<" + type + ">>(this." + name.text + ")" + (mem.args?.length ? '.' + mem.args[0] : '') + ") : \"null\"}";
|
|
137
|
+
mem.deserialize = "if (value_end - value_start == 4 && load<u64>(changetype<usize>(data) + <usize>(value_start << 1)) == " + charCodeAt64("null", 0) + ") {\n this." + name.text + " = null;\n } else {\n this." + name.text + " = " + "__DESERIALIZE<" + type + ">('{\"" + mem.args[0] + "\":' + data.substring(value_start, value_end) + \"}\");\n }";
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${this." + name.text + " ? __SERIALIZE(this." + name.text + (mem.args?.length ? '.' + mem.args[0] : '') + ") : \"null\"}";
|
|
141
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">('{\"" + mem.args[0] + "\":' + data.substring(value_start, value_end) + \"}\");";
|
|
142
|
+
}
|
|
143
|
+
mem.name = name.text;
|
|
144
|
+
}
|
|
127
145
|
const t = mem.node.type.name.identifier.text;
|
|
128
146
|
if (this.schemasList.find(v => v.name == t)) {
|
|
129
|
-
mem.initialize = "this." + name.text + " = changetype<nonnull<" +
|
|
147
|
+
mem.initialize = "this." + name.text + " = changetype<nonnull<" + mem.type + ">>(__new(offsetof<nonnull<" + mem.type + ">>(), idof<nonnull<" + mem.type + ">>()));\n changetype<nonnull<" + mem.type + ">>(this." + name.text + ").__INITIALIZE()";
|
|
130
148
|
}
|
|
131
149
|
else if (mem.value) {
|
|
132
150
|
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
@@ -348,6 +366,7 @@ var PropertyFlags;
|
|
|
348
366
|
PropertyFlags[PropertyFlags["OmitNull"] = 2] = "OmitNull";
|
|
349
367
|
PropertyFlags[PropertyFlags["OmitIf"] = 3] = "OmitIf";
|
|
350
368
|
PropertyFlags[PropertyFlags["Alias"] = 4] = "Alias";
|
|
369
|
+
PropertyFlags[PropertyFlags["Flatten"] = 5] = "Flatten";
|
|
351
370
|
})(PropertyFlags || (PropertyFlags = {}));
|
|
352
371
|
class Property {
|
|
353
372
|
constructor() {
|
package/transform/package.json
CHANGED
package/transform/src/index.ts
CHANGED
|
@@ -117,6 +117,10 @@ class JSONTransform extends BaseVisitor {
|
|
|
117
117
|
if (!decorator.args?.length) throw new Error("Expected 1 argument but got zero at @omitif in " + node.range.source.normalizedPath);
|
|
118
118
|
mem.args?.push((decorator.args[0] as StringLiteralExpression).value);
|
|
119
119
|
mem.flag = PropertyFlags.OmitIf;
|
|
120
|
+
} else if ((<IdentifierExpression>decorator.name).text == "flatten") {
|
|
121
|
+
if (!decorator.args?.length) throw new Error("Expected 1 argument but got zero at @flatten in " + node.range.source.normalizedPath);
|
|
122
|
+
mem.flag = PropertyFlags.Flatten;
|
|
123
|
+
mem.args = [(decorator.args[0] as StringLiteralExpression).value];
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
}
|
|
@@ -138,11 +142,21 @@ class JSONTransform extends BaseVisitor {
|
|
|
138
142
|
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${__SERIALIZE<" + type + ">(this." + name.text + ")}";
|
|
139
143
|
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));"
|
|
140
144
|
mem.name = name.text;
|
|
145
|
+
} else if (mem.flag == PropertyFlags.Flatten) {
|
|
146
|
+
const nullable = (mem.node.type as NamedTypeNode).isNullable;
|
|
147
|
+
if (nullable) {
|
|
148
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${this." + name.text + " ? __SERIALIZE(changetype<nonnull<" + type + ">>(this." + name.text + ")" + (mem.args?.length ? '.' + mem.args[0]! : '') + ") : \"null\"}";
|
|
149
|
+
mem.deserialize = "if (value_end - value_start == 4 && load<u64>(changetype<usize>(data) + <usize>(value_start << 1)) == " + charCodeAt64("null", 0) + ") {\n this." + name.text + " = null;\n } else {\n this." + name.text + " = " + "__DESERIALIZE<" + type + ">('{\"" + mem.args![0]! + "\":' + data.substring(value_start, value_end) + \"}\");\n }";
|
|
150
|
+
} else {
|
|
151
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${this." + name.text + " ? __SERIALIZE(this." + name.text + (mem.args?.length ? '.' + mem.args[0]! : '') + ") : \"null\"}";
|
|
152
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">('{\"" + mem.args![0]! + "\":' + data.substring(value_start, value_end) + \"}\");";
|
|
153
|
+
}
|
|
154
|
+
mem.name = name.text;
|
|
141
155
|
}
|
|
142
156
|
|
|
143
157
|
const t = (mem.node.type as NamedTypeNode).name.identifier.text;
|
|
144
158
|
if (this.schemasList.find(v => v.name == t)) {
|
|
145
|
-
mem.initialize = "this." + name.text + " = changetype<nonnull<" +
|
|
159
|
+
mem.initialize = "this." + name.text + " = changetype<nonnull<" + mem.type + ">>(__new(offsetof<nonnull<" + mem.type + ">>(), idof<nonnull<" + mem.type + ">>()));\n changetype<nonnull<" + mem.type + ">>(this." + name.text + ").__INITIALIZE()";
|
|
146
160
|
} else if (mem.value) {
|
|
147
161
|
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
148
162
|
}
|
|
@@ -362,7 +376,8 @@ enum PropertyFlags {
|
|
|
362
376
|
Omit,
|
|
363
377
|
OmitNull,
|
|
364
378
|
OmitIf,
|
|
365
|
-
Alias
|
|
379
|
+
Alias,
|
|
380
|
+
Flatten
|
|
366
381
|
}
|
|
367
382
|
|
|
368
383
|
class Property {
|