Install tipify dependency.
npm install --save tipify
Enable experimental decorators in tsconfig.
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
...
Instantiate a new converter.
const converter = new JsonConverter();
const car = new Car();
const json = converter.serialize(car);
const car2 = converter.deserialize(json, Car);
@jsonObject()
should be set on each class;
@jsonProperty('name', String)
should be set on each class field;
Type defined with @jsonProperty()
can be :
- A class decorated with
@jsonObject()
- A custom converter
- A type defined below
@jsonObject(#) | Type |
---|---|
String | string |
Number | number |
Boolean | boolean |
arrayOf(Passenger) | Passenger[] |
arrayOf(array(String)) | string[][] |
enumOf(Color) | Color |
any() | any |
keyValueOf(String, Passenger) | {[key:string]: Passenger} |
@jsonObject()
export class Passenger {
@jsonProperty('pid', PidConverter)
private _pid: Pid;
@jsonProperty('gender', enumOf(Gender, EnumStrategy.NAME))
private _gender: Gender;
@jsonProperty('name', String)
private _name: string;
@jsonProperty('informations', any())
private _informations: object;
constructor(options?: PassengerOptions) {
if (options) {
this._pid = options.pid;
this._gender = options.gender;
this._name = options.name;
this._informations = options.informations;
}
}
}
When type is not specified in @jsonProperty
decorator, mapper will try to get type information from emitted metadata.
Warning : It does not works with array and generics.
@jsonObject()
export class Passenger {
@jsonProperty('id')
private _id: number;
@jsonProperty('name')
private _name: string;
@jsonProperty('active')
private _active: boolean;
@jsonProperty('airline')
private _airline: Airline;
}
Tipify can manage polymorphism when discriminatorProperty
and discriminatorValue
are defined.
@jsonObject({discriminatorProperty: 'type'})
export abstract class Vehicle {
@jsonProperty('type')
private _type: string;
constructor(type?: string) {
this._type = type;
}
}
@jsonObject({discriminatorValue: 'car'})
export class Car extends Vehicle {
constructor() {
super('car');
}
}
const result = converter.deserialize({ "type" : "car" }, Vehicle);
chai.expect(result).instanceof(Car);
@jsonProperty('color', enumOf(Color, EnumStrategy.NAME_COMPATIBLE))
private _color: Color;
NAME_COMPATIBLE | |
NAME | |
INDEX_COMPATIBLE | |
INDEX |
export const pidConverter: CustomConverter<Pid, CustomConverterArgs> = {
deserialize(obj: any): Pid {
if (isNullOrUndefined(obj)) {
return obj;
}
return {
id: parseInt(obj, 10),
} as Pid;
},
serialize(obj: Pid): any {
if (isNullOrUndefined(obj)) {
return obj;
}
return obj.id;
},
};
Tipify can parse boolean and numbers when option tryParse
is enabled.
Note: Parsing is enabled by default;
const converter = new JsonConverter({ deserialize: { tryParse: true }});
const result = converter.deserialize('true', Boolean);
To serialize objects wrapped into non typed objects, use options unsafe: true
.
const car = new Car({brand: 'dodge', name: 'charger'});
const obj = [{charger: [car]}];
const result = converter.serialize(obj, undefined, {unsafe: true});
console.log(result);
// [{"charger":[{"brand":"dodge","type":"car","name":"charger"}]}]
Tipify will keep value initialized by class by default:
@jsonProperty('name', String)
public _name = 'titi';
A given JSON:
{}
is deserialized into:
{ _name: 'titi' }
This feature can be disabled with:
const converter = new JsonConverter({ deserialize: { keepObjectFieldValues: false } })
Note: Tipify use the constructor to create an instance.