Giter VIP home page Giter VIP logo

typescript-json-serializer's Introduction

Hi there ๐Ÿ‘‹

I'm Gillian, welcome to my Github profile!

โœ๏ธ I'm an author of an open-source Typescript library to serialize/deserialize json objects into classes: typescript-json-serializer.

๐Ÿ˜ An Angular lover, traversing each release since AngularJS.

๐Ÿง™ A styling/CSS wizard (according to my colleagues).

๐Ÿฆง And currently experimenting Rust.

typescript-json-serializer's People

Contributors

civilizeddev avatar dependabot[bot] avatar gillianperard avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

typescript-json-serializer's Issues

How to handle constructors?

Looking for some guidance on this. I get a lot of errors like this:

Property 'employees' has no initializer and is not definitely assigned in the constructor. ts (2564)

Do you have a recommended work around while using the strictPropertyInitialization flag?

Issues with async and await

Hi

I'm getting the following:

/home/nico/dev/projects/pidman/node_modules/typescript-json-serializer/index.js:285
            name: key.toString(),
                      ^

TypeError: Cannot read property 'toString' of undefined
    at getJsonPropertyValue (/home/nico/dev/projects/pidman/node_modules/typescript-json-serializer/index.js:285:23)
    at /home/nico/dev/projects/pidman/node_modules/typescript-json-serializer/index.js:103:20

This happens just right after I use the async and await functionality.

E.g. Class' method before async/await. This works with Serializable annotation. No errors here:

	kill(signal?: NodeJS.Signals): boolean {
		let ret = true;

		this.processes.forEach((process) => {
			ret = ret && (process.kill(signal));
		});

		return ret;
	}

e.g. same class' method after applying async and await. Error is thrown then:

	kill(signal?: NodeJS.Signals): boolean {
		let ret = true;

		this.processes.forEach(async (process) => {
			ret = ret && (await process.kill(signal));
		});

		return ret;
	}

I use the serializer library like this:

@Serializable()
export class WhateverClass {

And I only set one property as serializable on the constructor:

constructor(@JsonProperty() private options: GroupOptions)

Like said, it works pretty well without async/await... no matter where I use these keywords.

Please advise.

Thanks

Issues with enums

Hey id really like to use this libary, but iam running into the following issue

given is this snipped:

export enum ActionType {
  PlaySound = "PLAY_SOUND",
  Delay= "DELAY"
}

@Serializable()
export class Action {
  @JsonProperty()
  public type: ActionType
  
  @JsonProperty()
  public id: string
  
  @JsonProperty()
  public wait: boolean
  
  constructor(type: ActionType, id: string = uuid()) {
    this.type = type;
    this.id = id;
    this.wait = true;
  }
  
  public async Run(runner: MacroRunner): Promise<unknown> {
    return;
  }

  public Stop(): void {}
}

@Serializable()
export class Delay extends Action {
  private cancel: boolean = false;

  @JsonProperty()
  public delay: number;

  constructor(delay: number = 1000, id: string = uuid()) {
    super(ActionType.Delay, id);
    this.delay = delay;
  }

  public async Run(): Promise<unknown> {
    return new Promise(resolve => {
      const handle = setTimeout(resolve, this.delay)
      const cancelIntervalHandle = setInterval(() => {
        if (this.cancel) {
          clearTimeout(handle)
          clearInterval(cancelIntervalHandle)
          resolve();
        }
      }, 1)
    })
  }

  public Stop() {
    this.cancel = true;
  }
}

@Serializable()
class Test {
  @JsonProperty({
    predicate: (data: Action) => {
      if (data.type === ActionType.Delay) return Delay
    },
  }) public actions: Array<Action> = []
  constructor(actions: Array<Action>) { 
    this.actions = actions;
  }
}

const raw = {
  actions: [{
    type:"DELAY",
    id:"01e8b54a-8384-4c1f-a8a3-7ad103371fab",
    wait:true,
    cancel:false,
    delay:500,
    extra: true
  }]
}

const test = deserialize<Test>(raw, Test);

Delay extends the Action class and has an additional delay: number property. However this runs into the following issue:

IMG

What am i missing here?

Edit: when i declare Action.type as a string it works but then iam missing the enum part
EditEdit: when i move the enum below the Action class, it works. Is that intended? Can you explain that because it makes no sense in my head :D

Deserialize Array

Hi, I'm struggling to deserialize an array with this deserialize<Array<User>>(json, Array<User>). I get the error Argument of type 'User[]' is not assignable to parameter of type 'new (...params: any[]) => User[]'. How do I go about deserializing an array? Any help is appreciated. Thanks

Recursive types that extend another class

I have a type like:

@Serializable() export class Root { @JsonProperty({ name: "expressions", predicate: ExpressionType}) public expressions: Array<Expression>; }

There are two more types that extend Expression, they are:

@Serializable("Expression") export class ExpressionGroup extends Expression { @JsonProperty({ name: "expressions", predicate: ExpressionType }) public expressions: Array<Expression>; }

AND

@Serializable("Expression") export class Statement extends Expression { @JsonProperty() public field: string; @JsonProperty() public operator: Operator; @JsonProperty() public value: string; }

When I call deserialize, the Array off of Root appears to contain the correct types. However, the first element of this array is an ExpressionGroup, and it's Array was not converted into the right types, it is just an Object. Putting a console.log("called") inside the predicate function "ExpressionType" seems to be hit only once, presumably on Root's Array.

Is there a limitation in deeply nested arrays?

Warning in Chrome Console

When this package is used with Angular 10/11, the Angular framework produces a warning in the browser console:
The warning looks like this:

some_file.ts depends on 'typescript-json-serializer'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies.

Apparently there is some upgrade required to avoid potential performance issues with latest Angular versions.

About nested class deserializing

Hi @GillianPerard , I'm Ash in Korea.

I'm interested in your json-serializer, it is a great product I have ever seen it in Typescipt.

And I wonder if I use it correctly, it can't deserialize the case of nested class.

import { Serializable, JsonProperty } from 'typescript-json-serializer';
import { SR_Status } from './SR_Status';
import { ContentEntry } from './ContentEntry';

@Serializable()
export class GetContentEntries_2C_1 {

	public readonly ID: string  = "GetContentEntries.2C.1";

	@JsonProperty("id")
	public id: string;

	@JsonProperty("st")
	public status: SR_Status;

	@JsonProperty({ name : "es", type: ContentEntry })
	public entries: Array<ContentEntry>;

	public constructor() {
		this.id = this.ID;
		this.status = new SR_Status();
		this.entries = new Array<ContentEntry>();
	}
}

//deserialize
const m = deserialize<GetContentEntries_2C_1>(msg,GetContentEntries_2C_1);  

//result
id: string; 
entries : object
status : object

When I try to deserialize this class,

"this.entries" and "status" remained just an object.

So I need to deserialize with each type again.

Could you let me know, it is the intended way or what am I missing something?

Thanks for your cool product.

Cannot read property of 'name' of undefined

When I package a simple data transfer to a 3rd party API to an Winx64 .exe via the node pkg package, I get this error.

C:\Users\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\build>registria-win.exe -s "daisy" -b "LIN01" -r "1049315-1049318
TypeError: Cannot read property 'name' of undefined
    at convertDataToProperty (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\node_modules\typescript-json-serializer\index.js:164:24)
    at C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\node_modules\typescript-json-serializer\index.js:92:29
    at Array.forEach (<anonymous>)
    at Object.deserialize (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\node_modules\typescript-json-serializer\index.js:90:10)
    at RegistriaData.<anonymous> (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\build\registriaData.js)
    at step (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\build\registriaData.js)
    at Object.next (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\build\registriaData.js)
    at fulfilled (C:\snapshot\Jbaszler\OneDrive\Documents\Personal Stuff\Larson\Code Projects\Registria\registriaBackEnd\build\registriaData.js)

It runs just fine in the dev/debug environment. I've attached the few files that are in play for this.
psRegistria.ts.txt
registriaData.ts.txt
tsconfig.json.txt
nodemon.json.txt
package.json.txt
registria.ts.txt

Wrong parsed metadata on constructor parameters with JsDoc comment

Thank you for your last work on this.

It works, but ...

@Serializable()
export class Student {
  constructor(
    @JsonProperty()
    public readonly studentId: number,
    
    @JsonProperty()
    public readonly name: string,
    
    @JsonProperty()
    public readonly grade: number
  ) {}
}

Now it works. It's very convenient.

It fails when with JsDoc on constructor parameters

I found in some circumstance it failed.

For example,

@Serializable()
export class Student {
  constructor(
    /**
     * Student ID (KEY)
     */
    @JsonProperty()
    public readonly studentId: number,
    
    /**
     * Student's name
     */
    @JsonProperty()
    public readonly name: string,
    
    /**
     * Class grade that student belongs to
     */
    @JsonProperty()
    public readonly grade: number
  ) {}
}

It's not working.

console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } /**Student ID (KEY)*/
console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } /**Student's name*/
console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } /**Class grade that student belongs to*/

Counter example

@Serializable()
export class Student {
  /**
   * Student ID (KEY)
   */
  @JsonProperty()
  public readonly studentId: number

  /**
   * Student's name
   */
  @JsonProperty()
  public readonly name: string

  /**
   * Class grade that student belongs to
   */
  @JsonProperty()
  public readonly grade: number

  constructor(
    readonly studentId: number,
    readonly name: string,
    readonly grade: number
  ) {
    this.studentId = studentId
    this.name = name
    this.grade = grade
  }
}

It works.

console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } studentId
console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } name
console.log ../node_modules/typescript-json-serializer/index.js:47
  Student { key: [Getter] } grade

Thank you!

enum serilaization/deserialization error

Hello,

I tried to deserialize an object tree in which I have some enum properties (React App).
During the test, I got errors on type.name.toLowerCase() in convertDataToProperty.
I got also an error in castSimpleData on type.toLowerCase().
Looks like it couldn't get the type of my enum.
export enum ELoggingState {
Stopped = 0,
Paused = 1,
Running = 2,
}
So, I modified the source code to get rid of those errors.
Did you ever heard problem with enums ?
If you want, I can create a pull request with my modifications.

Kine Regards,
Laurenr.

property.toISOString()

Date can be undefined

    if (propertyType.name.toLocaleLowerCase() === Type.Date) {
        return property.toISOString();
    }

maybe something like this

    if (propertyType.name.toLocaleLowerCase() === Type.Date) {
        return property?property.toISOString():property;
    }

How to deserialize dynamic property?

Hello, I want to deserialize the following class:

class Foo {
    type: string;
    value: any;
}

The type of value will be depend on type (e.g. if type is name the value will be string). The closest thing I can find to achieve this is using predicate but the problems is I can't access type from there.

feat: add support for "merging" properties

After the update to 2.0.0 this serializer works like a charm in my project. Thanks!

But to really use this in my project, the feature is missing that i can kinda "merge" the properties from my incoming JSON into one property in my TS class.

Example:
`@Serializable()
class A {
@JsonProperty({ names: ["x", "y", "z"], onDeserialize: deserializeNested })
coordinates: { x: number, y: number, z: number };
}

const data: any = {
x: 1382,
y: 3134,
z: 313
};

const deserialized = deserialize(data, A)`

So that in the function defined in onDeserialize i have an array of the properties i defined in the names in the decorator.

Would it be possible to add this feature to the typescript-json-serializer ?

Thanks in advance!

Key In not deserializing properly

classes

@Serializable()
export class Character {
  @JsonProperty() spec: Spec;
  @JsonProperty() gear: { [key in GearSlots]: Item }                                   // PROBLEM HERE
  @JsonProperty() baseStats: ItemStats;
  @JsonProperty() race: Race

  // class functions
}

@Serializable()
export class Item {
  @JsonProperty() name: string = '';
  @JsonProperty() id: number = 0;
  @JsonProperty() _id: number;
  @JsonProperty() stats: ItemStats = {};
  @JsonProperty() validSlot: GearSlots | null;
  @JsonProperty() gemSockets: GemSocket[] = [];
  @JsonProperty() gemSocketBonus: ItemStats = {};
  @JsonProperty() set: GearSet = GearSet.none;
  @JsonProperty() weaponType?: WeaponType

  // class functions
}

@Serializable()
export class Spec {

  @JsonProperty() talents!: TalentMap;
  @JsonProperty() talentString: string;

  // class functions
}

In my service file

  saveCharacter() {
    const characterJson = serialize(this.character.value, false)
    localStorage.setItem('character', JSON.stringify(characterJson));
  }

  loadCharacter() {
    const characterJson = localStorage.getItem('character');
    if (characterJson) {
      const character = deserialize(JSON.parse(characterJson), Character)
      console.log(character instanceof Character);
      console.log(character.spec instanceof Spec);
      console.log(character.gear.head instanceof Item);                                      // PROBLEM HERE
      this.character.next(character);
  }

When I call loadCharacter()

output:
true
true
false

JsonSerializable Class inherited in --prod build does not get JsonProperty

Steps to reproduce:

  • Create a Serializable Class that extends another Serializable class, with at least one more JsonProperty
  • Observe correct serialization behavior in test mode with experimentalDecorators:True
  • COmpile --prod
  • Observe the additional JsonProperty is not populated by the constructors in prod build

New version onDeserialize definition breaks compatibility

Hey. I saw an update and was excited to try it but unfortunately i've stumbled upon compilation errors in my project.

#98 breaks compatibility with previous versions but it marked as patch version and not major.

This breaks the code because it defines a function as returning an object. But for example in my project i use this for simple data and not for objects.
https://github.com/GillianPerard/typescript-json-serializer/pull/98/files#diff-a2a171449d862fe29692ce031981047d7ab755ae7f84c707aef80701b3ea0c80R18

Example from the project i am working on

@JsonProperty({
    name: 'ImageId',
    onDeserialize: (id: number | undefined) => {
        return id ? getUrl(id) : undefined;
    },
})
Image?: string;

I think in type definition it should return any instead of {}.

Issue with dates serialization and deserialization

Hi everyone,

I have a small issue with date serialization and deserialization in my current project, I made a reproducer that you can find on stackblitz.

Basically, I'm trying to serialize and deserialize an object containing a Date using custom functions for onDeserialize and onSerialize (I have some custom Date magic in my app that I removed from the reproducer to make it more readable).

The problem is that the onSerialize function receives a string and not a Date and I don't understand why. I can workaround the problem by re-creating a Date from the string but I should not have to do that.

Thanks

Support for predicate function

Example:

@JsonProperty({}, (animal: Animal) => {
    return animal['isPoisonous'] ? Snake : Panther;
})
public pantherOrSnake: Panther | Snake;

Nested property of Array<T> does not serialize properly

Hi Gillian.

First, thanks for you efforts and your contributions!

I'm using typsecript-json-serializer v2.1.0

I've found that properties which are an Array of serializable objects do not serialize correctly...

Given the following model definition:

@Serializable()
export class Person {
    @JsonProperty()
    public name: string;
    @JsonProperty()
    public children?: Array<Person>;
    public parent?: Person;
}

The parent in this case is NOT decorated with @JsonProperty and therefore should NOT appear when serialized.

However I'm finding that when I perform the following (from my .spec.ts file):

        const child = new Person();
        child.name = 'Child';

        const parent = new Person();
        parent.name = 'Parent';
        parent.children = [child];

        child.parent = parent;

        const json = serialize(parent);
        expect(json.children[0].parent).toBeUndefined();

I find that my test case is failing as follows:

expect(received).toBeUndefined()

    Received: {"children": [{"name": "Child", "parent": [Circular]}], "name": "Parent"}

Note that the Parent property has been stripped as expected from the Parent instance but still remains in the child instance. I have proven this by setting breakpoints and inspecting both the "parent" and "json" objects after serialization.

To prove this theory I created a second class "Person2" whose only difference is that instead of an Array of children I have simply a single child of type Person2:

@Serializable()
export class Person2 {
    @JsonProperty()
    public name: string;
    @JsonProperty()
    public child?: Person2;
    public parent?: Person2;
}

In this case, the exact same test setup as above passes and inspecting the serialized object yield no Parent property.

This is true even if I nest further (i.e. Grandparent > Parent > Child).

It therefore appears that the JsonProperty (or lack of in this case) is being ignored when it's an Array...

Is this a bug or have I done something stupid?

deserialization with constructor

This test doesn't work for me

@Serializable()
class MyClass{
    @JsonProperty()
    someString:string = 'default'

    @JsonProperty()
    someNumber:number

    constructor(
        @JsonProperty()
        public constructorProperty:string,

        @JsonProperty()
        public anotherConstructorProperty:string = 'another default value'
    ){

    }
}

const x = new MyClass('x constructor property')
x.constructorProperty = '!!!'
x.anotherConstructorProperty = '!!!'
x.someString = '!!!'
x.someNumber = 2
console.log('x=', x)
const string1 = JSON.stringify(serialize(x))
console.log('string1=', string1)

const y = deserialize(string1, MyClass)
const string2 = JSON.stringify(serialize(y))
console.log('y=', y)
console.log('string2=', string2)
console.log('string1==string2 ?', string1 == string2)

I'm expecting all fields to be copied to new object.

output:

x= MyClass {
  constructorProperty: '!!!',
  anotherConstructorProperty: '!!!',
  someString: '!!!',
  someNumber: 2
}
string1= {"someString":"!!!","someNumber":2,"anotherConstructorProperty":"!!!","constructorProperty":"!!!"}
y= MyClass {
  constructorProperty: undefined,
  anotherConstructorProperty: 'another default value',
  someString: 'default'
}
string2= {"someString":"default","anotherConstructorProperty":"another default value"}
string1==string2 ? false

Can you please check?

More verbose errors

Currently if there is an error in deserialization it's not possible to tell where it happend, on what property/object.

0: Type number is not assignable to type boolean.

I propose to make them more verbose in terms of when the error happend.

Type 'number' is not assignable to type 'boolean' in property 'XXX` on type `YYY`.

Or something like that.

Thanks.

Separating serializer/deserializer from the type itself

I'm pretty sure this one would be a biggy, but for the next major release perhaps I would love to see the serializers/deserializers being separated from the types themselves.
This would have two main benefits:

  • a foreign class (defined in a library perhaps) can be made serializable by the user code
  • possibly multiple serializers could be defined for the same class (to comply with multiple APIs operating on the data, using different representations)

I would envision it to work something along the lines:

export class LivingBeing {
    id: number;
}

export class Human extends LivingBeing {
    constructor(
        public id: number,
        public readonly birthDate: Date
    ) {
        super();
        this.id = id;
    }
}

@Serializer(LivingBeing)
export interface LivingBeingSerializer {
    @JsonProperty() id: number;
}

@Serializer(Human)
export interface HumanSerializer extends LivingBeingSerializer {
      @JsonProperty('humanId') public name: string,
      public id: number,
      @JsonProperty() public gender: Gender,
      @JsonProperty() public readonly birthDate: Date
}

@Serializer(Human)
export interface HumanSerializer2 extends LivingBeingSerializer {
      @JsonProperty() public name: string,
      public id: number,
      @JsonProperty() public gender: Gender,
      @JsonProperty() public readonly birthDate: Date
}

const human = deserialize<Human>(json, HumanSerializer); // reads name from "humanId"
const human = deserialize<Human>(json, HumanSerializer2); // reads name from "name"

Although I do not currently have free time to work on this, I just wanted to put this on the ideas table

TypeError: Cannot read property 'toString' of undefined

After adding an import to the following class, I'm facing an error:

@Serializable()
export class MyClass1 {
    @JsonProperty() id: string = '1';
}
Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined
    at getJsonPropertyValue (index.js?c608:284)
    at eval (index.js?c608:85)
    at Object.decorateElement (myclass1.ts:23)
    at Object.eval (myclass1.ts:23)
    at Array.forEach (<anonymous>)
    at Object.decorateClass (myclass1.ts:23)
    at _decorate (myclass1.ts:21)
    at eval (myclass1.ts?eef3:6)
    at Module../src/libraries/my-lib/myclass1.ts (0.js:1959)
    at __webpack_require__ (app.js:833)

Not working with typeorm eager

If im trying serialize entity with eager field im getting error

cannot read property "name" of undefined

Can u try to reproduce

import * as ORM from "typeorm";
import Node from "./node";
import {Serializable, JsonProperty} from "typescript-json-serializer"


@ORM.Entity({name: 'gates'})
@Serializable()
export default class Gate {

    @ORM.PrimaryGeneratedColumn({name: "id"})
    @JsonProperty({name: 'id'})
    public id: number;

    @ORM.Column({unique: true, name: 'sn'})
    @JsonProperty({name: 'serialNumber'})
    public serialNumber: string;

    @ORM.OneToMany(type => Node, node => node.gate)
    public nodes: Node[];

    public changeSerialNumber (serialNumber: string) {
        this.serialNumber = serialNumber;
    }
}
import * as ORM from "typeorm";
import Gate from "./gate";
import Location from "./location"
import {Serializable, JsonProperty} from "typescript-json-serializer"


@ORM.Entity({name: 'nodes'})
@Serializable()
export default class Node {

    @ORM.PrimaryGeneratedColumn({name: 'id'})
    @JsonProperty({name: 'id'})
    public id: number;

    @ORM.ManyToOne(type => Gate, { onDelete: "CASCADE", onUpdate: "CASCADE", eager: true })
    @ORM.JoinColumn({name: "gates_id"})
    @JsonProperty()
    public gate: Gate;

    @ORM.PrimaryColumn({unique: true, name: 'sn'})
    @JsonProperty({name: 'serialNumber'})
    public serialNumber: string;

    @ORM.Column({type: "tinyint", name: 'status'})
    @JsonProperty({name: 'status'})
    public status: Status = Status.DOWN;

    @ORM.Column({default: 120, name: 'downtime_timeout'})
    @JsonProperty({name: 'downtimeTimeout'})
    public downtimeTimeout: number;

    @ORM.Column({default: false, name: 'downtime_timeout_enabled'})
    @JsonProperty({name: 'downtimeTimeoutEnabled'})
    public downtimeTimeoutEnabled: boolean;

    @ORM.ManyToOne(type => Location, { onDelete: "SET NULL", onUpdate: "CASCADE" })
    @ORM.JoinColumn({name: 'locations_id'})
    @JsonProperty({name: 'location'})
    public location: Location;

    @ORM.CreateDateColumn({type: "timestamp", name: 'created_at'})
    @JsonProperty({name: 'createdAt'})
    public readonly createdAt: string;

    @ORM.Column({name: 'visible', default: true, type: "tinyint"})
    @JsonProperty({name: 'visible'})
    public visible: boolean = true;

    @ORM.Column({name: 'alias', nullable: true, default: null})
    @JsonProperty({name: 'alias', onSerialize: (v) => !v ? "" : v})
    public alias: string;

    public changeGate(gate: Gate) {
        this.gate = gate;
    }


    public changeSerialNumber(serialNumber: string) {
        this.serialNumber = serialNumber;
    }

    public changeVisible(visible: boolean){
        this.visible = visible;
    }

    public changeAlias(alias: string){
        this.alias = alias;
    }

    public changeLocation(location: Location) {
        this.location = location;
    }

    public changeStatus(status: Status) {
        this.status = status;
    }

    public get frequency(): number {
        if(!this.gate.contract) {
            return 10;
        }

        if(this.gate.contract.settings.frequency < 1) {
            return 1;
        }

        return this.gate.contract.settings.frequency;
    }
}

export enum Status {
    PRODUCTION                  = 1,
    DOWN                        = 2,
    WAITING_ON_MAINTENANCE      = 3,
    WAITING_ON_MATERIAL_HANDLER = 4,
    SETUP_ADJUSTMENT_NEEDED     = 5,
    WAITING_ON_SELLER           = 6
}
const node = new Node();
const gate = new Gate();
node.gate = gate;

const str = serialize(node);

Inheritance and property overrides

Hey. So the issue is this

@Serializable()
class BaseClass {
    @JsonProperty('ID')
    Id: number;
}

@Serializable()
class ChildClass extends BaseClass {
    @JsonProperty('Item_ID')
    Id: number;
}
{
    "Item_ID": 12
}
const data = deserialize(json, ChildClass);
console.log(data.Id); // undefined

If I try to override json property name in inherited class I get undefined value because it tries to find ID and not Item_ID although I parse ChildClass and not BaseClass.

Attributes to serialize a dictionnary

Hello,
Serialising an Array requires JsonProperty to be like
@JsonProperty( {type: ColumnReference })
public columns: Array <ColumnReference> = [];

Now I guess that there must be some JsonProperty to specify for a dictionary defined like:
public someDic: { [id: string]: ColumnReference } = {};

can one tell me what should @JsonProperty be for the above example ?

Thanks.

feat: add deep inheritance support

Thanks for creating typescript-json-serializer I have found it very useful !

I have a use case where I have multi level inheritance e.g. class B extends A and class C extends B where all the classes declare some properties that are annotated with @JsonProperty when calling serialize on an instance of class C the resulting JSON data only contains the properties declared on class C and B but not the properties declared on class A. I would expect the resulting JSON data to contain the fields marked as Json Properties on all parent classes.

Example:

@Serializable()
abstract class A {
    @JsonProperty()
    a: string;
}

@Serializable("A")
abstract class B extends A {
    @JsonProperty()
    b: string;
}

@Serializable("B")
class C extends B {
    @JsonProperty()
    c: string
}

const instance: C = new C();
instance.a = "aaa";
instance.b = "bbb";
instance.c = "ccc";

const data: any = serialize(instance);
/**
 * data = {
 *     b: "bbb",
 *     c: "ccc"
 * }
 * 
 * I expect data to be
 * {
 *     a: "aaa",
 *     b: "bbb",
 *     c: "ccc"
 * }
 */

Is it possible to update typescript-json-serializer to handle multiple level inhertance and include annotated properties from all parent classes ?

Thanks for your time.

JPSav.

Support a Reverse Predicate Function

Would it be possible to support a reverse predicate function?

Right now I have a problem where I have JSON with a lot of extra layers:

JSON:

{
    A: {
        B: {
            C: {
                D: "value"
             }
         }
    }
}

Target Class:

class A {
    private D: string;
}

Right now I solve this using a predicate function:

function(obj)
{
    return obj["C"]["D"];
}

However, this does not work with deserialization. Having an unpredicate function (need a better name) would allow a function like this:

function(obj)
{
    return { B: { C: { D: obj } } }
}

That would allow deserializing back to the original extra layer state.

@JsonProperty() in getters

Is it possible to add @JsonProperty decorator to a getter function?

@Serializable()
class MyClass {
  @JsonProperty()
  get myProperty(): string { return this.myProperty }
}

Feature: Extend Transform Function to Include Reference to Parent Element

It would be incredibly nice for the transform function to also be passed a reference to the parent element.

Consider the following structure:

@Serializable()
export class MyClass {
   @JsonProperty()
   public id: number;
   @JsonProperty()
   public name: string;
   public parent: MyClass;
   @JsonProperty({ type: MyClass, onDeserialize: deserializeChildren })
   public children: Array<MyClass>;
}

...
const parent = new MyClass();
parent.id = 1;
parent.name = 'Parent'

const child = new MyClass();
child.id = 2;
child.name = 'Child';
child.parent = parent;

parent.children = [child1];
...

We have previously had discussions around the merits/problems of such a circular reference of the Parent referencing the Child. This is a necessary navigation in my structure and is perfectly fine until I need to serialize... (circular is fine when we're using references at runtime but problematic when you attempt to serialize unless the framework is "smart" enough to use references...).

At any rate, it's for this reason that the "parent" property of MyClass is transient (i.e. NOT marked as a JsonProperty). In this way, the parent relationship is stripped on serialize and no circular relationship exists in the serialized structure.

However, the difficulty comes when I attempt to deSerialize... When resaturating the MyClass instance I need to reestablish the parent relationship...

My original thought was to have a transform function on the "children" attribute and simply populate the parent... however this necessitates an actual reference to the parent which is not (or doesn't appear to be) available.

Another option would be to have some form of "postSerialize" function that you could attach to the @serializable() decorator which would permit me to do any number of "cleanup" steps to the instance as a whole (I can envision many reasons that this might be a useful tool).

Either of the two mechanisms above would work for me in my scenario although adding the parent reference to the parameter list of the transform seems somewhat case-specific.

Would either of the above be something you'd consider adding?

Additionally I'd be happy to hear about any other way you can see to solve my problem.

Cannot read property 'name' of undefined testing serialize

When I try to test a component that use serialize, I found this error

Cannot read property 'name' of undefined

Using the application it's work.
I use Jest, here the test(simplified, without component)

@Serializable()
export class ClassToTest {
  @JsonProperty() num: number;

  constructor() {}
}

describe('test', () => {

  it('test serialization', () => {
    debugger;
    const obj = new ClassToTest ();
    obj.num= 100;
    const serialized = serialize(obj); // here the error
    const deserialized = deserialize<ClassToTest >(serialized, ClassToTest );
    expect(deserialized .num).toBe(100);
  });

the tsconfig.json


{
  "compilerOptions": {
    "outDir": "../out-tsc/spec",
    "types": [
      "jest",
      "node"
    ],
    "module": "commonjs",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "allowJs": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "target": "es5"
  },
  "files": [
    "polyfills.ts"
  ],
  "include": [
    "**/*.spec.ts",
    "**/*.d.ts"
  ]
}

Extends with no additional JSON properties

Hi guys,
I have to serialize a class that extends another class but does not have any additional JSON properties, and that seems to break the lib. Here is a small reproducer:

import { Serializable, JsonProperty, serialize } from 'typescript-json-serializer';

@Serializable()
export class Animal {
    @JsonProperty()
    public id: number;
    @JsonProperty()
    public name: string;
    public constructor(name: string) {
        this.name = name;
    }
}

@Serializable('Animal')
export class Dog extends Animal {
  public constructor(@JsonProperty() public color: string, name: string) {
    super(name);
  }
}

@Serializable('Animal')
export class Cat extends Animal {
  public constructor(name: string) {
    super(name);
  }
}

const clifford = new Dog('red', 'Clifford');
console.log(serialize(clifford)); // -> {color: "red", name: "Clifford"}

const garfield = new Cat('Garfield');
console.log(serialize(garfield)); // -> {}

I should have { name: "Garfield" }, right?
Thanks!

"Cannot use import statement outside a module" when using versions > 3.0

After microbundle was added to this package, I see the error SyntaxError: Cannot use import statement outside a module whenever I try to use this library. I was able to create a simple reproduction using the code from the README.
Compiling and executing this:

import { Serializable, JsonProperty } from 'typescript-json-serializer'

@Serializable()
export class LivingBeing {

    @JsonProperty() id: number;
    constructor(id: number) {
        this.id = id;
        
    }
}

results in this error

/Users/darylwalleck/repos/ts-serializer-test/node_modules/typescript-json-serializer/dist/index.modern.js:1
import"reflect-metadata";function e(){return(e=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e}).apply(this,arguments)}var t;function r(e){const t=Reflect.getPrototypeOf(e);return t&&t.name?[...r(t),t.name]:[]}function a(r){return(a,n,i)=>{if(void 0===n&&a.prototype){const e=Reflect.getMetadata("design:paramtypes",a)[i];n=function(e){const t=e.toString().replace(/(\/\*[\s\S]*?\*\/|\/\/.*$)/gm,"").replace(/[\r\t\n\v\f]/g,"").replace(/( +)/g," "),r=/(?:this\.)([^\n\r\t\f\v;]+)([\s;])/gm,a=new Map,n=/(?:.*(?:constructor|function).*?(?=\())(?:\()(.+?(?=\)))/m.exec(t);if(!n||!n.length)return a;const i=n[1].replace(/ /g,"").split(",");let o;for(;o=r.exec(t);){const e=o[1].replace(/ /g,"").split("="),t=i.findIndex(t=>t===e[1]);t>-1&&a.set(t,e[0])}return a}(a.prototype.constructor).get(i),a=a.prototype,Reflect.defineMetadata("design:type",e,a,n)}let o={};const s=`api:map:${a.constructor.name}`;Reflect.hasMetadata(s,a)&&(o=Reflect.getMetadata(s,a)),o[n]=function(r,a){if(!a)return{name:r.toString(),isDictionary:!1,isNameOverridden:!1};let n;return n=typeof a===t.String?{name:a,isNameOverridden:!0}:a.name?{name:a.name,isNameOverridden:!0}:a.names&&a.names.length?{names:a.names}:{name:r.toString(),isNameOverridden:!1},n=e({},n,{beforeSerialize:a.beforeSerialize,afterSerialize:a.afterSerialize,beforeDeserialize:a.beforeDeserialize,afterDeserialize:a.afterDeserialize,isDictionary:!!a.isDictionary}),e({},n,a.predicate?{predicate:a.predicate}:{type:a.type})}(n,r),Reflect.defineMetadata(s,o,a)}}function n(e){return t=>{const a=r(t);Reflect.defineMetadata("api:map:serializable",{baseClassNames:a,options:e},t)}}function i(t,r){let a={};return t.forEach(t=>{a=e({},a,Reflect.getMetadata(`api:map:${t}`,r))}),a}function o(r,a){var n;if([null,void 0].includes(r))return r;if(void 0===a)return l(typeof r,r);const s=new a,f=s.constructor.name,{baseClassNames:p,options:u}=null!=(n=Reflect.getMetadata("api:map:serializable",a))?n:{},d=`api:map:${f}`,m=Reflect.hasMetadata(d,s);let y={};return m||p&&p.length?(y=Reflect.getMetadata(d,s),p&&p.length&&(y=e({},i(p,s),y)),Object.keys(y).forEach(e=>{const a=function(e,r,a,n,i){let s;if([null,void 0].includes(n))return n;if("names"in a){const e={};a.names.forEach(t=>e[t]=n[t]),s=e}else if("name"in a&&!a.isNameOverridden&&i){const e=i(a.name);s=n[e]}else s=n[a.name];if([null,void 0].includes(s))return s;const f=Reflect.getMetadata("design:type",e,r),p=!!f.name&&f.name.toLowerCase()===t.Array,u=a.isDictionary,d=a.predicate,m=a.beforeDeserialize,y=a.afterDeserialize;let g=a.type||f;const b=c(g);let v;if(m&&(s=m(s,e)),u){const a={};typeof s!==t.Object?(console.error(`Type '${typeof s}' is not assignable to type 'Dictionary' for property '${r}' in '${e.constructor.name}'.\n`,`Received: ${JSON.stringify(s)}`),v=void 0):(Object.keys(s).forEach(t=>{b||d?(d&&(g=d(s[t],s)),a[t]=o(s[t],g)):a[t]=l(typeof s[t],s[t],r,e.constructor.name)}),v=a)}else if(p){const t=[];Array.isArray(s)?(s.forEach(a=>{b||d?(d&&(g=d(a,s)),t.push(o(a,g))):t.push(l(typeof a,a,r,e.constructor.name))}),v=t):(console.error(`Type '${typeof s}' is not assignable to type 'Array' for property '${r}' in '${e.constructor.name}'.\n`,`Received: ${JSON.stringify(s)}`),v=void 0)}else b||d?(g=d?d(s,n):g,v=o(s,g)):v=l(g.name,s,r,e.constructor.name);return y&&(v=y(v,e)),v}(s,e,y[e],r,null==u?void 0:u.formatPropertyNames);void 0!==a&&(s[e]=a)}),s):s}function s(r,a=!0){var n;if([void 0,null].includes(r)||typeof r!==t.Object)return r;const o=`api:map:${r.constructor.name}`,{baseClassNames:l,options:f}=null!=(n=Reflect.getMetadata("api:map:serializable",r.constructor))?n:{},p=l&&l.length,u=Reflect.hasMetadata(o,r);let d={};if(!u&&!p)return r;d=Reflect.getMetadata(o,r),p&&(d=e({},i(l,r),d));const m={},y=Object.keys(r);return Object.keys(d).forEach(e=>{if(y.includes(e)){const n=d[e],i=n.beforeSerialize,o=n.afterSerialize;let l;i&&(l=r[e],r[e]=i(r[e],r));let p=function(e,r,a,n){const i=e[r],o=Reflect.getMetadata("design:type",e,r),l=!!o.name&&o.name.toLocaleLowerCase()===t.Array,f=a.predicate,p=a.type||o,u=c(p);if(i&&(u||f)){if(l)return i.map(e=>s(e,n));if(a.isDictionary){const e={};return Object.keys(i).forEach(t=>{e[t]=s(i[t],n)}),e}return s(i,n)}return p.name.toLocaleLowerCase()===t.Date&&typeof i===t.Object?i.toISOString():i}(r,e,n,a);if(o&&(p=o(p,r)),r[e]=l||r[e],n.names)n.names.forEach(e=>{(!a||a&&void 0!==p[e])&&(m[e]=p[e])});else if(!a||a&&void 0!==p)if(!n.isNameOverridden&&null!=f&&f.formatPropertyNames){const e=f.formatPropertyNames(n.name);m[e]=p}else m[n.name]=p}}),m}function c(e){return Reflect.hasOwnMetadata("api:map:serializable",e)}function l(e,r,a,n){if(null==e)return r;if(e=e.toLowerCase(),(typeof r).toLowerCase()===e)return r;const i=()=>{console.error(`Type '${typeof r}' is not assignable to type '${e}' for property '${a}' in '${n}'.\n`,`Received: ${JSON.stringify(r)}`)};switch(e){case t.String:const e=r.toString();return"[object Object]"===e?void i():e;case t.Number:const a=+r;return isNaN(a)?void i():a;case t.Boolean:return void i();case t.Date:return isNaN(Date.parse(r))?void i():new Date(r);default:return r}}!function(e){e.Array="array",e.Boolean="boolean",e.Date="date",e.Number="number",e.Object="object",e.String="string"}(t||(t={}));export{a as JsonProperty,n as Serializable,o as deserialize,s as serialize};
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:355:18)
    at wrapSafe (node:internal/modules/cjs/loader:1022:15)
    at Module._compile (node:internal/modules/cjs/loader:1056:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:996:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at Object.<anonymous> (/Users/darylwalleck/repos/ts-serializer-test/dist/index.js:13:38)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)

I'm not sure if this is a bug or an issue with my tsconfig.json . Here's the config I'm using:

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    "target": "es2020",
    "module": "commonjs",
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "declaration": true,
  },
  "include": [
    "src/**/*"
  ]
}

Any feedback would be appreciated. Thanks!

minified constructor parameter names after production-build

Description

Some packaging-for-production-distribution libraries, such as react-scripts (used by create-react-app), pkg (Node Binary Packager), minify JS file on its variable names. With it constructor parameter names are not preserved. It makes @JsonProprty() on constructor parameters not working.

Any idea on this?

Inital instance is changed during serialization

Hi!

I think there is a problem.
Why inital instance is mutated by serializer? For example, during beforeSerialization predicate works.
I think, it would be better when result of beforeSerialize() will not modify inital instance, but will be passed as an argument for serialize().

So current implementation can't be used with immutable data instance.
Am I right?

Serialize an external class

I have a class that has member of the type THREE.Vector3 (a 3 component vector from three.js). Can I define a custom serialization function for this member? (using .toArray() and .fromArray())

How to deserialize a generic class

I'm struggling with the following call that leads to a compiling error Value of type 'typeof MyClass' is not callable. Did you mean to include 'new'?

const rpcResponse = deserialize<RpcResponse<Data>>(responseJSON, RpcResponse<Data>);

Any idea how to fix this please ?

Support constructor parameter decorators

Hi, thank you for maintaining this project.

I hope this could be supported in the near future.

Current

@Serializable()
export class Student {
  @JsonProperty()
  public readonly studentId: number

  @JsonProperty()
  public readonly name: string

  @JsonProperty()
  public readonly grade: number

  constructor(
    readonly studentId: number,
    readonly name: string,
    readonly grade: number
  ) {
    this.studentId = studentId
    this.name = name
    this.grade = grade
  }
}
  • verbose
  • redundant code

Wanted

@Serializable()
export class Student {
  constructor(
    @JsonProperty()
    public readonly studentId: number,
    
    @JsonProperty()
    public readonly name: string,
    
    @JsonProperty()
    public readonly grade: number
  ) {}
}
  • succinct

References

the name of json property isn't changed when using nested structure.

I found an issue while I tested a case where a target class has a property whose type is same to its class. name property has name alias. So, I expected the last test line must have succeeded. But it failed.

The following is what I expected.
{"isSuperviser":false,"fullname":"andrew","superviser":{"isSuperviser":true,"fullname":"heath"}}

But, I got the following result.
{"isSuperviser":false,"fullname":"andrew","superviser":{"isSuperviser":true,"name":"heath"}}

As you can see, the name in the nested object wasn't changed. I'm wondering whether this behavior is intended or not.

You can check whole code below.

import { serialize, Serializable, JsonProperty } from 'typescript-json-serializer';

@Serializable()
export class Employee {
    @JsonProperty()
    public isSuperviser: boolean = false;

    @JsonProperty({
        name: "fullname"
    })
    public name: string = "";

    @JsonProperty()
    public superviser: Employee | undefined = undefined;

    public constructor() {}
}

describe("test typescript-json-serializer", () => {

    it("basic functionality", () => {

        let superv = new Employee();
        superv.isSuperviser = true;
        superv.name = "heath";

        let data = serialize(superv);
        expect(data.isSuperviser).toBe(true);
        expect(data.fullname).toBe("heath");
        expect(data.superviser).toBe(undefined);

        let emp = new Employee();
        emp.isSuperviser = false;
        emp.name = "andrew";
        emp.superviser = superv;

        data = serialize(emp);
        console.log(`data = ${JSON.stringify(data)}`);
        expect(data.isSuperviser).toBe(false);
        expect(data.fullname).toBe("andrew");
        expect(data.superviser.isSuperviser).toBe(true);
        expect(data.superviser.fullname).toBe("heath");
    });
});

Unable to set required fields

It there a way to set required fields when using deserialize?

For example if I have this object

@Serializable()
class User{
  @JsonProperty({ name: 'email' })
  private _email: string
  @JsonProperty({ name: 'password' })
  private _password: string

  constructor(email: string, password: string){
    this._email = email
    this._password = password
  }

  public get email(): string{
    return this._email
  }

  public set email(email: string){
    this._email = email
  }

I tried to deserialize a json which only has password { password: 'password123' }

const user = deserialize<User>(json, User)

The result model would return the email field as undefined.

I tried to use a predicate like this

@JsonProperty({ name: 'email', predicate: emailPredicate })

where

const emailPredicate = (_email: any) => {
  if(_email instanceof String){
    return String
  }else if(_email === undefined){
    throw new Error()
  }else {
    throw new Error()
  }
}

but it still returns a field email as undefined. Perhaps my approach is incorrect?

Serialize any or union type question

Hi, I have a question about the best way to deserialize an object with a member of type any.

Given the following model definition:

@Serializable()
export class Squirrel {

    constructor(
        @JsonProperty()
        public color: string,
        @JsonProperty()
        public data?: any
}

and then performing the following:

        let squirrel = new Squirrel('red', 'bushy-tailed-rat');
        let json = serialize(squirrel);
        const jsonString = JSON.stringify(json, null, 3);
        console.log(jsonString);

        json = JSON.parse(jsonString);
        squirrel = deserialize<Squirrel>(json, Squirrel);

This "works" however the data loses all type information when I use a non-primitive type - (not what I need)...

@Serializable()
export class NutData {

    constructor(
        @JsonProperty()
        public species: string
    ) { }

}

...
        let squirrel = new Squirrel('Red', new NutData('Oak'));
        let json = serialize(squirrel);
        const jsonString = JSON.stringify(json, null, 3);
        console.log(jsonString);

        json = JSON.parse(jsonString);
        squirrel = deserialize<Squirrel>(json, Squirrel);
...

The difficulty for is that the data member can be a number of different types including the primitive types string or number.

I've tried a number of different solutions... option 1: using a predicate and maintaining the data type of any:

export const dataPredicate = attribute => {

    if (attribute['species'] !== undefined) {
        return NutData;
    }

    if (typeof attribute === 'number') {
        return Number; // this is suspect however using 'number' results in a compile error.
    }

    if (typeof attribute === 'string') {
        return String; // also suspect...
    }
};

@Serializable()
export class Squirrel {

    constructor(
        @JsonProperty()
        public color: string,
        @JsonProperty({ predicate: dataPredicate })
        public data?: any) { }

}

Running this through my test scripts yields the following error:

TypeError:

      249 |     );
      250 |     const apiMapInstanceName = `${apiMap}${instanceName}`;
    > 251 |     const hasMap = Reflect.hasMetadata(apiMapInstanceName, instance);
          |                            ^
      252 |     let instanceMap: { [id: string]: Metadata } = {};
      253 | 
      254 |     if (!hasMap && (!baseClassNames || !baseClassNames.length)) {

      at Object.hasMetadata (node_modules/reflect-metadata/Reflect.js:270:23)
      at serialize (src/index.ts:251:28)
      at convertPropertyToData (src/index.ts:324:16)
      at src/index.ts:269:24
          at Array.forEach (<anonymous>)
      at Object.serialize (src/index.ts:265:30)
      at Object.<anonymous> (spec/index.spec.ts:325:16)

I note that the predicate is never even evaluated... So I then attempted to use a union type:

@Serializable()
export class Squirrel {

    constructor(
        @JsonProperty()
        public color: string,
        @JsonProperty({ predicate: dataPredicate })
        public data?: NutData | string | number) { }

}

This resulted in an identical error leading me to believe that there's something fundamentally wrong with what I'm doing.

Can you suggest what the configuration should be in the above scenario?

I have considered wrapping all possibilities in an 'DataClass' class but this doesn't seem to be terribly maintainable:

@Serializable()
export class DataClass {

    constructor(
        @JsonProperty()
        public nutData?: NutData,
        @JsonProperty()
        public stringData?: string,
        @JsonProperty()
        public numberData?: number
    ) { }
}

@Serializable()
export class Squirrel {

    constructor(
        @JsonProperty()
        public color: string,
        @JsonProperty()
        public data?: DataClass) { }

}

Any suggestions would be greatly appreciated!

Getting TypeError When Integrating with React Native

Thank you for the solution. Promises to be awesome.

Though I'm getting 'TypeError : undefined is not an object (evaluating type.name)' error

Here is my code

import { serialize, JsonProperty, Serializable } from 'typescript-json-serializer';

@Serializable()
class TestObject {
  @JsonProperty({ name: "Title" }) title: string
  @JsonProperty("IDNumber") ID: number
  constructor(ID: number, title: string) {
    this.title = title
    this.ID = ID;
  }
}

 let mObject = new TestObject(10, "Test Object");
 let json = serialize(mObject,false); //Whether true or false

optional properties cause reversibility problems

@Serializable()
class Queue implements PubSub.Entity<string> {
  @JsonProperty() id?: string;
  @JsonProperty() name: string;
  @JsonProperty() description?: string;
  constructor(name: string) {
    this.name = name;
  }
}

const q = new Queue('fred')
q.id = '123'
const q2 = deserialize(JSON.parse(JSON.stringify(serialize(q))), Queue)
expect(q).to.be.instanceOf(Queue)
expect(q2).to.be.instanceOf(Queue)

// this fails because { id: '123', name: 'fred' } is not equal to { id: '123', 'name: 'fred', description: undefined }
expect(q).to.deep.equal(q2)

Is there some form of equality check in typescript which ignores the difference between optional property not existing and its value being undefined, or is there a way to deserialize optional properties so that they don't result in undefined values but are removed from the instance, instead?

ts 2307

I am brand new to typescript, VS code and all that stuff.

I have installed using npm install typescript-json-serializer --save as per the documentation

but I have an error shown in VS code : Cannot find module 'typescript-json-serializer' or its corresponding type declarations.ts(2307)
on this line :
import { JsonProperty, Serializable, deserialize, serialize } from 'typescript-json-serializer';

My project is using node.

my options are like:
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"module": "es6",
"pretty": false,
"sourceMap": true
},

when I change "module" to "commonjs" like this I don't have the error shown in VS code

my options are like:
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"module": "commonjs",
"pretty": false,
"sourceMap": true
},
the program compiles but when it starst, right after the browser opened I get:
Uncaught ReferenceError: require is not defined

I am very sorry if this looks stupid to you meanwhile I would appreciate some guidance.
Thx

Deserialize does not handle null

I have a JavaScript object that has some properties as null, eg:

const obj = JSON.parse(`{
    "field1": "some string",
    "field2": null,
    "field3": null,
    "field4": "something else"
}`);

I have a class using the @Serializable and @JsonProperty annotations:

@Serializable()
export class Dummy {
    @JsonProperty() field1?: string;
    @JsonProperty() field2?: string;
    @JsonProperty() field3?: string;
    @JsonProperty() field4?: string;
}

If I try to deserialize my JS object with:

const dummy: Dummy = deserialize<Dummy>(obj, Dummy);

I get:

TypeError: Cannot read property 'toString' of null

from castSimpleData.

isn't "null" a valid value for a property and shouldn't this be handled? Currently I just use an onDeserialize function that converts null to empty string to get around this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.