@lancercomet/suntori
v1.1.0
Published
A Typescript JSON de/serializer to ensure everything is safe at runtime
Downloads
63
Maintainers
Readme
SunTori
SunTori is a Typescript JSON de/serializer to ensure everything is safe at runtime.
Features
- JSON <--- Mapping ---> Class.
- JSON fields name <--- Mapping ---> Class props name.
- Typesafe at runtime.
- Deal with raw strings and dynamic keys.
First of all
SunTori depends on the very feature emitDecoratorMetadata
which was introduced to TypeScript, so keep in mind:
- Not available in pure JavaScript enviroment. You have to use it with TypeScript.
- Not available for ESBuild because ESBuild doesn't emit decorator metadata.
Installation
Install reflect-metadata:
npm install reflect-metadata --save
Import reflect-metadata
in the whole project entry:
// Project entry.
import 'reflect-metadata'
Remember to enable this two things in tsconfig.json
:
"emitDecoratorMetadata": true,
"experimentalDecorators": true
Usage
Deserialization.
import { Serializable, JsonProperty, deserialize } from '@lancercomet/suntori'
@Serializable()
class User {
@JsonProperty()
name: string = ''
@JsonProperty()
age: number = 0
@JsonProperty('user_address')
address: string = 'Default address'
}
const dataSource = {
name: 'Doge',
age: 1,
user_address: 'The Moon.'
}
const doge = deserialize(dataSource, User) // User
Array-typed deserialization.
import { Serializable, JsonProperty, deserialize } from '@lancercomet/suntori'
@Serializable()
class User {
@JsonProperty()
name: string = ''
@JsonProperty()
age: number = 0
@JsonProperty('user_address')
address: string = 'Default address'
}
@Serializable()
class UserList {
// Array-typed property must be described like this.
@JsonProperty({
name: 'users',
type: User
})
users: User[] = []
}
const dataSource = [
{ name: 'LancerComet', age: 10, user_address: 'The Mars.' },
{ name: 'John Smith', age: 100, user_address: 'The Heaven.' }
]
const userList = deserialize(dataSource, UserList) // User[]
Serialization.
@Serializable()
class User {
@JsonProperty()
name: string = ''
@JsonProperty()
age: number = 0
@JsonProperty('user_address')
address: string = 'Default address'
}
const dataSource = {
name: 'Doge',
age: 1,
user_address: 'The Moon.'
}
const doge = deserialize(dataSource, User) // User
const json = serialize(doge) // json should be "equal" to dataSource.
More decorators
There are also some additional decorators, providing extra functionalities.
@JsonString
import { Serializable, JsonProperty, deserialize, JsonString } from '@lancercomet/suntori'
@Serializable()
class A {
@JsonProperty()
a: string = ''
}
@Serializable()
class B {
@JsonProperty({
type: A,
name: 'list1'
})
list1: A[] = []
@JsonProperty({
type: A,
name: 'list2'
})
@JsonString() // <-- Add this.
list2: A[] = []
}
const b = deserialize({
list1: '[{ "a": "a1" }, { "a": "a2" }]', // Oh no.
list2: '[{ "a": "a1" }, { "a": "a2" }]' // Yeah!
}, B)
@DynamicKey
import { Serializable, JsonProperty, deserialize, DynamicKey } from '@lancercomet/suntori'
@Serializable()
class A {
@JsonProperty()
a: string = ''
}
@Serializable()
class B {
@JsonProperty({
name: 'as',
type: A
})
@DynamicKey() // <-- Add this.
as: { [key: string]: A } = {}
}
const b = deserialize({
as: {
a: {},
b: {},
c: {}
}
}, B)
@Nullable
@Serializable()
class A {
@JsonProperty()
readonly num: number = 0
@JsonProperty()
@Nullable() // <--- Add this.
readonly numNullable: number = 0
@JsonProperty()
@Nullable() // <--- Add this.
readonly numNullable2: number = 0
}
const a = deserialize({
num: null,
numNullable: null,
numNullable2: undefined
}, A)
console.log(a.num) // 0
console.log(a.numNullable) // null
console.log(a.numNullable2) // 0, only got null if payload were null.
@ParseInt and @ParseFloat
@Serializable()
class A {
@JsonProperty()
@ParseInt()
readonly int: number = 0
@JsonProperty()
@ParseFloat()
readonly float: number = 0
}
const a = deserialize({
int: '10',
float: '0.1'
}, A)
console.log(a.int) // 10
console.log(a.float) // 0.1
License
Apache-2.0