JairusSW / as-json

The only JSON library you'll need for AssemblyScript. SIMD enabled
MIT License
79 stars 15 forks source link

Support optional serializing of properties #52

Closed mattjohnsonpint closed 10 months ago

mattjohnsonpint commented 1 year ago

Consider:

@json
class Person {
  constructor(public firstName: string, public lastName: string) {}

  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
};

...

const p = new Person("John", "Doe")
const s = JSON.stringify(p);

output:

{"firstName":"John","lastName":"Doe"}

How might I indicate that I want fullName included in the output?

With JavaScript, I can do that by explicitly specifying the requested fields. In other words:

const s = JSON.stringify(p, ['firstName', 'lastName', 'fullName']);

I could see that working here as well. Alternatively, perhaps we can do something with decorators on the property itself, such as:

  @json(include: true)
  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }

Thoughts?

JairusSW commented 1 year ago

Perhaps we could make it default to serialize/deserialize if a getter/setter pair exists which would be implemented in the transform.

I like the idea of having an option argument JSON.stringify<T, C>(data: T, config: C): string, but I'm not sure how deeply string matching would impact performance.

Another option could be to use some sort of comment...

// include: fullName
@json
class Vec3 {
class Person {
  constructor(public firstName: string, public lastName: string) {}

  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
}

Any of these could totally be implemented. I ordered them top-to-bottom for complexity

JairusSW commented 1 year ago

@casimiro, looping you in here. Supporting default values (https://github.com/JairusSW/as-json/issues/51) kind of loops in here. Currently, as-json just allocates empty space for the class, so default values and all values are uninitialized.

One other solution here is to parse out to a object, string, number, variable, ect..

@json
class Vec3 {
    x: f64 = 3.4;
    y: f64 = 1.2;
    z: f64 = 8.3;
}

const parsedVec = new Vec3();
// Default values initialized. Do whatever logic you want here.

JSON.parseTo<Vec3>(parsedVec, '{"y":8.4}');

console.log(JSON.stringify(parsedVec));
// serializeTo function would also be implemented, solving the default types (optionally)
// {
//    "x": 3.4,
//    "y": 8.4,
//    "z": 8.3
// }

When parsing to strings or a pre-allocated object (so as to prevent realloc).

const out = "";

JSON.parseTo<string>(out, '"hello world"');
// out = "hello world"
JSON.parseTo<string>(out, '"its modified"');
// out = "its modified"

What do you think?

casimiro commented 1 year ago

@JairusSW I really like the idea of parsing out to an object -- it favours efficiency and the interface remains simple and clear.

JairusSW commented 1 year ago

I'm on Thanksgiving break, so I'm planning to spend some time on this. :)

JairusSW commented 1 year ago

Implemented in latest version. I will implement parsing out to an object later as that is really cool