Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
typescript-json-serializer
Advanced tools
Readme
A typescript library to deserialize json into typescript classes and serialize classes into json.
npm install typescript-json-serializer --save
# or
yarn add typescript-json-serializer
You also need to set experimentalDecorators and emitDecoratorMetadata to true into the tsconfig.json file.
For example:
{
"compilerOptions": {
...
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
...
}
}
import { JsonSerializer, throwError } from 'typescript-json-serializer';
import { json } from '../json/data';
import { Organization } from '../models/organization';
// Instantiate a default serializer
const defaultSerializer = new JsonSerializer();
// Or you can instantiate a serializer with your custom options
const customSerializer = new JsonSerializer({
// Throw errors instead of logging
errorCallback: throwError,
// Allow all nullish values
nullishPolicy: {
undefined: 'allow',
null: 'allow'
},
// Disallow additional properties (non JsonProperty)
additionalPropertiesPolicy: 'disallow',
// e.g. if all the properties in the json object are prefixed by '_'
formatPropertyName: (propertyName: string) => `_${propertyName}`,
})
// Deserialize
const organization = defaultSerializer.deserialize(json, Organization);
// Serialize
const data = defaultSerializer.serialize(organization);
// Import decorators from library
import { JsonObject, JsonProperty } from 'typescript-json-serializer';
// Enums
export enum Gender {
Female,
Male,
Other
}
export enum Status {
Alive = 'Alive',
Sick = 'Sick',
DeadAndAlive = 'Dead and alive',
Dead = 'Dead'
}
// Create a JsonObject class: LivingBeing
// JsonObject decorator
@JsonObject()
export class LivingBeing {
/** The living being id (PK) */
@JsonProperty() id: number;
}
// Create a JsonObject class that extends LivingBeing: Human
@JsonObject()
export class Human extends LivingBeing {
constructor(
// This comment works
// Override LivingBeing id property name
// and set required to true
@JsonProperty({name: 'humanId', required: true})
public id: number,
@JsonProperty() public name: string,
@JsonProperty() public gender: Gender,
/** This comment works */
@JsonProperty() public readonly birthDate: Date
) {
super();
this.id = id;
}
}
// Create a JsonObject class: PhoneNumber
@JsonObject()
export class PhoneNumber {
@JsonProperty() countryCode: string;
@JsonProperty() value: string;
}
// Create a JsonObject class that extends Human: Employee
@JsonObject()
export class Employee extends Human {
/** The employee's email */
@JsonProperty({required: true}) email: string;
/** Predicate function to determine if the property type
* is PhoneNumber or a primitive type */
@JsonProperty({
type: property => {
if (property && property.value !== undefined) {
return PhoneNumber;
}
}
})
phoneNumber: PhoneNumber | string;
constructor(
public name: string,
// Override human id property name
// (keep the require to true from Human id)
@JsonProperty('employeeId') public id: number,
public gender: Gender,
public birthDate: Date
) {
super(name, id, gender, birthDate);
}
}
// Create a JsonObject class that extends LivingBeing: Animal
@JsonObject()
export class Animal extends LivingBeing {
@JsonProperty() name: string | undefined;
@JsonProperty() birthDate: Date;
@JsonProperty() numberOfPaws: number;
@JsonProperty() gender: Gender;
// Enum value (string)
@JsonProperty() status: Status;
// Specify the property name of json property if needed
@JsonProperty('childrenIdentifiers')
childrenIds: Array<number>;
constructor(name: string | undefined) {
super();
this.name = name;
}
}
// Create a JsonObject class that extends Animal (which extends LivingBeing): Panther
@JsonObject()
export class Panther extends Animal {
@JsonProperty() color: string;
// JsonProperty directly inside the constructor
// for property parameters
public constructor(
name: string | undefined,
@JsonProperty() public isSpeckled: boolean
) {
super(name);
}
}
// Create a JsonObject class that extends Animal (which extends LivingBeing): Snake
// When the library instatiates a class during deserilization it does not know the constructor params value
// so you need to specify them.
// To ways are available
// - by passing default value to those params in the constructor
// - by passing the `constructorParams` options to `JsonObject` (see below); it allows to keep clean constructor
@JsonObject({ constructorParams: [{}] })
export class Snake extends Animal {
@JsonProperty() isPoisonous: boolean;
public constructor(args: { name: string | undefined; isPoisonous: boolean }) {
super(args.name);
this.isPoisonous = args.isPoisonous;
}
}
// Create a JsonObject empty class that extends Animal (which extends LivingBeing): UnknownAnimal
@JsonObject()
export class UnknownAnimal extends Animal {
public constructor(name: string) {
super(name);
}
}
// Create a JsonObject class: Zoo
// Function to transform coordinates into an array
const coordinatesToArray = (coordinates: {
x: number;
y: number;
z: number;
}): Array<number> => {
return Object.values(coordinates);
};
// Function to transform an array into coordinates
const arrayToCoordinates = (array: Array<number>): {
x: number;
y: number;
z: number
} => {
return {
x: array[0],
y: array[1],
z: array[2]
};
};
// A predicate function use to determine what is the
// right type of the data (Snake or Panther)
const snakeOrPanther = animal => {
return animal && animal['isPoisonous'] !== undefined
? Snake
: Panther;
};
@JsonObject()
export class Zoo {
// Here you do not need to specify the type
// inside the decorator
@JsonProperty() boss: Employee;
@JsonProperty() city: string;
@JsonProperty() country: string;
// Property with transform functions executed respectively
// on serialize and on deserialize
@JsonProperty({
beforeDeserialize: arrayToCoordinates,
afterSerialize: coordinatesToArray
})
coordinates: { x: number; y: number; z: number };
// Possibly undefined Set of none-basic type elements
@JsonProperty({ type: Employee, dataStructure: 'set' })
employees: Set<Employee> | undefined;
@JsonProperty() id: number;
@JsonProperty() name: string;
// Array of none-basic type elements where you need to
// specify the name of the json property
// and use the predicate function to cast the deserialized
// object into the correct child class
@JsonProperty({ name: 'Animals', type: snakeOrPanther })
animals: Array<Animal>;
// Property that can be Panther or Snake type
// Use again the predicate function
@JsonProperty({ type: snakeOrPanther })
mascot: Panther | Snake;
// Dictionary of empty child classes
@JsonProperty({ dataStructure: 'dictionary', type: UnknownAnimal })
unknownAnimals: { [id: string]: UnknownAnimal };
// Map of array of PhoneNumber or string
@JsonProperty({
type: property => {
if (property?.value !== undefined) {
return PhoneNumber;
}
}
})
phoneBook: Map<string, Array<PhoneNumber | string>>;
// Property which will be not serialized and deserialized
// but event accessible and editable from Zoo class.
public isFree: boolean = true;
public constructor() { }
}
// Create a JsonObject generic class: Value
@JsonObject()
export class Value<R> {
@JsonProperty() value: R;
constructor(value: R) {
this.value = value;
}
}
// Create a JsonObject class: Item
@JsonObject()
export class Item {
@JsonProperty({ name: 'name' })
private readonly _name: string;
@JsonProperty({ name: 'version' })
private readonly _version: number;
constructor(name: string, version: number) {
this._name = name;
this._version = version;
}
}
// Create a JsonObject class that extends Society: Organization
@JsonObject()
export class Organization extends Society {
@JsonProperty({ type: Zoo }) zoos: Array<Zoo>;
@JsonProperty({ dataStructure: 'dictionary' })
zoosName: { [id: string]: string };
// To merge multiple properties in a single one
// use the property `names`.
// If you don't create your own merge with the `beforeDeserialize`
// and `afterSerialize` function, it will just merge properties
// in this one when using `deserialize` and split back
// when using `serialize`
@JsonProperty({
name: [
'mainShareholder',
'secondaryShareholder',
'thirdShareholder'
],
type: Human,
beforeDeserialize: value => Object.values(value),
afterSerialize: value => {
return {
mainShareholder: value[0],
secondaryShareholder: value[1],
thirdShareholder: value[2]
};
}
})
shareholders: Array<Human>;
miscellaneous: Value<Item>;
}
// Create a JsonObject class: Society
@JsonObject()
export class Society {
// Here note the `required` option with the default value `'4'`
// it will not throw because the default value will be set instead of `undefined`
@JsonProperty({ required: true }) id: string = '4';
@JsonProperty() name: string;
}
// data.ts
export const data: any = {
name: 'Zoos Organization',
zoosName: {
'15': 'The Greatest Zoo',
'16': 'Zoo Zoo'
},
zoos: [
{
id: 15,
name: 'The Greatest Zoo',
city: 'Bordeaux',
coordinates: [1, 2, 3],
country: 'France',
boss: {
employeeId: 1,
name: 'Bob Razowsky',
birthDate: '1984-04-03T22:00:00.000Z',
email: 'bob.razowsky@tgzoo.fr',
gender: 1,
phoneNumber: '111-111-1111'
},
employees: [
{
employeeId: 1,
name: 'Bob Razowsky',
birthDate: '1984-04-03T22:00:00.000Z',
email: 'bob.razowsky@tgzoo.fr',
gender: 1,
phoneNumber: '111-111-1111'
},
{
employeeId: 2,
name: 'Mikasa Ackerman',
birthDate: '1984-01-11T22:00:00.000Z',
email: 'mikasa.ackerman@tgzoo.fr',
gender: 0,
phoneNumber: '222-222-2222'
},
{
employeeId: 3,
name: 'Red Redington',
birthDate: '1970-12-04T22:00:00.000Z',
email: 'red.redington@tgzoo.fr',
gender: 1,
phoneNumber: '333-333-3333'
},
{
employeeId: 4,
name: 'Fried Richter',
birthDate: '1994-04-01T22:00:00.000Z',
email: 'fried.richter@tgzoo.fr',
gender: 1
}
],
Animals: [
{
id: 1,
name: 'Bagheera',
birthDate: '2010-01-11T22:00:00.000Z',
numberOfPaws: 4,
gender: 1,
childrenIdentifiers: [2, 3],
color: 'black',
isSpeckled: false,
status: 'Sick'
},
{
id: 2,
birthDate: '2017-03-10T22:00:00.000Z',
numberOfPaws: 4,
gender: 0,
color: 'blond',
isSpeckled: true,
status: 'Alive'
},
{
id: 3,
name: 'Ka',
birthDate: '2018-09-09T00:00:00.000Z',
numberOfPaws: 0,
gender: 1,
isPoisonous: true
},
{
id: 4,
name: 'Schrodinger',
numberOfPaws: 4,
gender: 1,
color: 'brown',
isSpeckled: false,
status: 'Dead and alive'
}
],
mascot: {
id: 1,
name: 'Bagheera',
birthDate: '2010-01-11T22:00:00.000Z',
numberOfPaws: 4,
gender: 1,
childrenIdentifiers: [2, 3],
color: 'black',
isSpeckled: false,
status: 'Sick'
},
unknownAnimals: {
'1': {
name: null
}
},
phoneBook: {
'1': [
{ value: '111-111-1111' },
{ value: '444-444-4444' }
],
'2': [{ value: '222-222-2222' }],
'3': ['333-333-3333']
}
},
{
id: 16,
name: 'Zoo Zoo',
city: 'Paris',
coordinates: [4, 2, 3],
country: 'France',
boss: {
employeeId: 2,
name: 'Sully',
birthDate: '1984-08-03T22:00:00.000Z',
email: 'sully.razowsky@tgzoo.fr',
gender: 1,
phoneNumber: {
countryCode: '33',
value: '0111111111'
}
},
employees: [],
Animals: [],
mascot: null,
unknownAnimals: {}
}
],
mainShareholder: {
humanId: 100,
name: 'Elon Musk',
birthDate: '1971-06-28T22:00:00.000Z',
gender: 1
},
secondaryShareholder: null,
miscellaneous: {
value: {
name: 'Item A',
version: 1
}
}
};
@JsonObject()
Used to make a class serializable.
options
Type: JsonObjectOptions
Optional: true
Description: The option to customize the serialization/deserialization of the target class.
@JsonObject(options)
class MyClass {}
@JsonProperty()
Used to make a class property serializable, property will be ignored if not set.
options
Type: string
| JsonPropertyOptions
Optional: true
Description: The option to customize the serialization/deserialization of the target property.
@JsonProperty(options) myProperty: string;
constructor(options?: Partial<JsonSerializerOptions>) {}
options
Type: Partial<JsonSerializerOptions>
Optional: true
Description: The options to customize the serializer.
options
Type: Partial<JsonSerializerOptions>
Optional: false
Description: The options to customize the serializer.
Default value:
{
errorCallback: logError,
nullishPolicy: {
undefined: 'remove',
null: 'allow'
},
additionalPropertiesPolicy: 'remove'
}
deserialize()
To use when you don't know if the value to deserialize is an object or an array.
deserialize<T extends object>(
value: string | object | Array<object>,
type: Type<T> | T
): T | Array<T|Nullish> | Nullish
value
Type: string
| object
| Array<object>
Optional: false
Description: The value to deserialize.
type
Type: Type<T>
| T
Optional: false
Description: The constructor class to deserialize into.
T
or Array<T|Nullish>
or Nullish
deserializeObject()
To use when the value to deserialize is an object.
deserializeObject<T extends object>(
obj: string | object,
type: Type<T> | T
): T | Nullish
obj
Type: string
| object
Optional: false
Description: The object to deserialize.
type
Type: Type<T>
| T
Optional: false
Description: The constructor class to deserialize into.
T
or Nullish
deserializeObjectArray()
To use when the value to deserialize is an array.
deserializeObjectArray<T extends object>(
array: string | Array<any>,
type: Type<T> | T
): Array<T|Nullish> | Nullish
array
Type: string
| Array<any>
Optional: false
Description: The object to deserialize.
type
Type: Type<T>
| T
Optional: false
Description: The constructor class to deserialize into.
serialize()
To use when you don't know if the value to serialize is an object or an array
serialize(value: object | Array<object>): object | Array<object|Nullish> | Nullish
value
Type: object
| Array<object>
Optional: false
Description: The object or the array of objects to serialize.
object
or Array<object|Nullish>
or Nullish
serializeObject()
To use when the value to serialize is an object.
serializeObject(instance: object): object | Nullish
instance
Type: object
Optional: false
Description: The object to serialize.
object
or Nullish
serializeObjectArray()
To use when the value to serialize is an array of objects.
serializeObjectArray(array: Array<object>): Array<object|Nullish> | Nullish
array
Type: Array<object>
Optional: false
Description: The array of objects to serialize.
Array<object|Nullish>
or Nullish
constructorParams?: Array<unknown>;
name?: string | Array<string>;
type?: Function | PredicateProto;
dataStructure?: DataStructure;
required?: boolean;
beforeSerialize?: IOProto;
afterSerialize?: IOProto;
beforeDeserialize?: IOProto;
afterDeserialize?: IOProto;
errorCallback?: ErrorCallback = logError;
nullishPolicy: NullishPolicy = {
undefined: 'remove',
null: 'allow'
};
additionalPropertiesPolicy: Policy = 'remove';
formatPropertyName?: FormatPropertyNameProto;
undefined: Policy;
null: Policy;
'array' | 'dictionary' | 'map' | 'set'
null | undefined
'allow' | 'disallow' | 'remove'
(message: string) => void
The library provide two built-in methods:
logError
that logs the error.throwError
that throws the error.(propertyName: string) => string;
(property: any, currentInstance?: any) => any
(property: any, parentProperty?: any) => any
new (...args: Array<any>) => T;
Note: represent a constructor
.
yarn
yarn build
yarn lint
yarn test
Gillian Pérard - @GillianPerard
FAQs
Typescript library to serialize classes into json and deserialize json into classes.
The npm package typescript-json-serializer receives a total of 5,517 weekly downloads. As such, typescript-json-serializer popularity was classified as popular.
We found that typescript-json-serializer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.