No description
dist | ||
src | ||
types | ||
.gitignore | ||
package-lock.json | ||
package.json | ||
README.md | ||
tsconfig.json |
serde-json-ts
a (de)serializer for serde-ts
Usage
fromString
and toString
are provided as easy entrypoints into the (de)serializer. JSONSerializer
and JSONDeserializer
are also directly usable in more complex scenarios
Example
import { Null, registerSerialize, registerDeserialize } from 'serde'
import { ISerializer } from 'serde/ser'
import { forward, IDeserializer, IIterableAccess, IMapAccess } from 'serde/de'
import { fromString, toString } from 'serde-json-ts'
toString(true) // "true"
toString(null) // "null"
toString({ test: 1 }) // '{"test":1}'
toString([1, 2, 3]) // '[1,2,3]'
fromString("true", Boolean) // true
fromString("null", Null) // null
fromString('{"test":1}', Object) // { test: 1 }
fromString('[1,2,3]', Array) // [1, 2, 3]
class Recipient {
static {
registerSerialize(Recipient, Recipient.serialize<string>)
registerDeserialize(Recipient, Recipient.deserialize)
}
readonly displayName: string
private readonly email: string
constructor(displayName: string, email: string,) {
this.displayName = displayName
this.email = email
}
static serialize<T>(serializer: ISerializer<T>, recipient: Recipient) {
// there's no real reason to serialize it this way other than
// we can. not good for production though
return serializer.serializeString(`${recipient.displayName}<${recipient.email}>`)
}
static deserialize(deserializer: IDeserializer) {
return deserializer.deserializeString({
visitString(value: string) {
let [displayName, email] = value.split('<')
email = email.slice(0, -1)
return new Recipient(displayName, email)
}
})
}
}
class Message {
static {
registerSerialize(Message, Message.serialize<string>)
registerDeserialize(Message, Message.deserialize)
}
readonly from: Recipient
readonly to: Recipient[]
readonly text: string
constructor(from: Recipient, to: Recipient[], text: string) {
this.from = from
this.to = to
this.text = text
}
static serialize<T>(serializer: ISerializer<T>, message: Message) {
// we could hint that the size is 3, but json doesn't care about size, only shape. same
const serializeObj = serializer.serializeObject()
serializeObj.serializeEntry('from', message.from)
serializeObj.serializeEntry('to', message.to)
serializeObj.serializeEntry('text', message.text)
return serializeObj.end()
}
static deserialize(deserializer: IDeserializer) {
// signal to the deserializer that we are expecting an object
return deserializer.deserializeObject({
visitObject(access: IMapAccess) {
let from, to, text
for (const [key, value] of access) {
switch (key) {
case 'from':
from = forward(value, Recipient)
break
case 'to':
to = value.map((v: any) => forward(v, Recipient))
break
case 'text':
text = value
break
}
}
return new Message(from, to, text)
}
})
}
}
const bob = new Recipient('Bob', 'bob@security.lol')
const alice = new Recipient('Alice', 'alice@balloon.party')
const alicesMom = new Recipient("Alice's Mom", 'alice.mom@malware.zip')
const message = new Message(bob, [alice, alicesMom], 'i hope this email finds you before i do')
const messageSerial = toString(message)
console.log(messageSerial)
// {"from":"Bob<bob@security.lol>","to":["Alice<alice@balloon.party>","Alice's Mom<alice.mom@malware.zip>"],"text":"i hope this email finds you before i do"}
const messageDecereal = fromString(messageSerial, Message)
console.log(messageDecereal)
/*
Message {
from: Recipient { displayName: 'Bob', email: 'bob@security.lol' },
to: [
Recipient { displayName: 'Alice', email: 'alice@balloon.party' },
Recipient {
displayName: "Alice's Mom",
email: 'alice.mom@malware.zip'
}
],
text: 'i hope this email finds you before i do'
}
*/