# serde-json-ts a (de)serializer for [serde-ts](https://git.kitsu.cafe/rowan/serde-ts) # Usage ```ts 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) registerDeserialize(Recipient, Recipient.deserialize) } readonly displayName: string private readonly email: string constructor(displayName: string, email: string,) { this.displayName = displayName this.email = email } static serialize(serializer: ISerializer, 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) 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(serializer: ISerializer, 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","to":["Alice","Alice's Mom"],"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' } */ ```