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 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.3
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
@@ -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 Base {}
5
- @json
6
- class Vec1 extends Base {
7
- x: f64 = 1.0;
5
+ class Vec3 {
6
+ x: f32 = 0.0;
7
+ y: f32 = 0.0;
8
+ z: f32 = 0.0;
8
9
  }
9
- @json
10
- class Vec2 extends Vec1 {
11
- @omit()
12
- y: f32 = 2.0;
10
+
11
+ class Box<T> {
12
+ value: T;
13
13
  }
14
+
14
15
  @json
15
- class Vec3 extends Vec2 {
16
- z: f32 = 3.0;
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 arr: Base[] = [
20
- new Vec1(),
21
- new Vec2(),
22
- new Vec3()
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(JSON.stringify(arr));
49
+ console.log("Stringified: " + stringified);
50
+ console.log("Parsed: " + JSON.stringify(parsed));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -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<" + t + ">>(__new(offsetof<nonnull<" + t + ">>(), idof<nonnull<" + t + ">>()));\n changetype<nonnull<" + t + ">>(this." + name.text + ").__INITIALIZE()";
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() {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -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<" + t + ">>(__new(offsetof<nonnull<" + t + ">>(), idof<nonnull<" + t + ">>()));\n changetype<nonnull<" + t + ">>(this." + name.text + ").__INITIALIZE()"
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 {