Closed mrgatto closed 3 years ago
Unfortunately, We don't provide a built-in json serializer.
As you may know, Attributes can be defined as private
field and implement custom serde function using getter/setters.
For example:
@Decorator.Table()
class Room extends Table {
// ... truncated
// Date serde
@Decorator.Attribute()
private createdAtTimestamp: number;
public get createAt(): Date {
return new Date(this.createdAtTimestamp);
}
public set createdAt(date: Date) {
this.createdAtTimestamp = date.getTime();
}
// Binary encoded value serde
//
// CREATE_INSTANT_INVITE | 0x01 (1 << 0) | Allows creation of instant invites
// EMBED_LINKS | 0x02 (1 << 1) | Links sent by users with this permission will be auto-embedded
// ATTACH_FILES | 0x04 (1 << 2) | Allows creation of instant invites
@Decorator.Attribute()
public encodedPermissions: number;
public get inviteAllowed(): boolean {
return Boolean(this.encodedPermissions & 0x01);
}
public set inviteAllowed(allow: boolean) {
this.encodedPermissions = allow
? this.encodedPermissions | 0x01
: this.encodedPermissions & ~0x01
}
}
Dynamorm know which class properties are DynamoDB Attribute, but there's no way to figure out whether given property is public or not. These limitations make it hard to make decisions - That's why we don't provide a built-in json serializer. you must implement your own toJSON
method to convert given Entity instance to plain object.
For example:
@Decorator.Table
export class Entity extends Table {
@Decorator.Attribute({ name: "MY_ID" })
code: number
public toJSON() {
return {
code: this.code,
};
}
}
const entity = new Entity()
entity.code = 10
const json = JSON.stringify(entity) // will be `{"code": 10}`. toJSON method will be automatically called by JSON.stringify.
const obj = entity.toJSON(); // of course you can use serialized object if needed
Ok, I ended up with a generic implementation.
public toJSON(): T {
const tableClass = (this as any).writer.tableClass
const model = {}
tableClass.metadata.attributes.forEach(atr => {
model[atr.propertyName] = this.getAttribute(atr.name)
})
return <T>model
}
And to not expose internal attributes of the lastEvaluatedKey:
const result = new APIQueryResponse()
result.content = ... // toJSON of records
result.count = queryResult.count
const lastKeys = queryResult.lastEvaluatedKey || {}
for (const key of Object.keys(lastKeys)) {
const tableClass = (records[0] as any).writer.tableClass
const property = tableClass.metadata.attributes.find(atr => atr.name == key)
result.lastEvaluatedKey[property.propertyName] = lastKeys[key]
}
Is there a way to maintain the class structure on stringify an object ?
What I expected:
What it actualy returns: