Code Monkey home page Code Monkey logo

cerialize's People

Contributors

1ambda avatar antitoine avatar buonjg avatar ceymard avatar christophercr avatar marcelhoogesteger avatar rodolfosilva avatar weichx 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  avatar  avatar  avatar  avatar  avatar

cerialize's Issues

Refactor code

Hey @weichx good work.

I think we can turn this project most better breaking the serializer.ts separing the responsibilities and creating a index.ts to join all. What do you think about this?

Deserialize bad in Union Types

@deserializeAs(ParameterValue | GetResponseValue)
it doesn't work anyway.

how can i deserialise str to the union type instance?

Deserialize circular referenced classes

Suppose there are two classes: Post and Comment.

class Post {
  @autoserialize
  id: string;

  @deserializeAs(Comment)
  comments: Comment[];
}

class Comment {
  @autoserialize
  id: string;

  @deserializeAs(Post)
  post: Post;
}

When deserialize a post with comments, it failed to deserialize the comments:

Input:

{
  "id": "foo",
  "comments": [
    {
      "id": "comment-1"
    }
  ]
}

Output:

let post = Deserialize(json, Post);
expect(post.comments).not.toBeUndefined() // failed!

This implementation might seems odd, but I suppose it's a valid use case to have bidirectional association that I can lookup the relevant objects from either side.

  • Is there any limitation on the deserializer?
  • Is there a way to implement the association?

Thanks!

Custom Objects

I had to change

if (metadata.deserializedType && typeof (<any>metadata.deserializedType).Deserialize === "function") {
            instance[keyName] = (<any>metadata.deserializedType).Deserialize(source);
}

TO

if (metadata.deserializedType && typeof (<any>metadata.deserializedType).Deserialize === "function") {
            instance[keyName] = **new** (<any>metadata.deserializedType).Deserialize(source);
}

in order to maintain object type.

If you skip new here you get an anonymous object.

--- Background

I used @autoserializeAs(MyObject)

but what i got on deserialisation was a anonymous Object without the methods I expected the Object to have (MyObject).

I would appreciate an opinion to this or if i missed something.

Greetings

IE11: Deserialize fails to parse "0001-01-01" dates

There is a bug with the Deserialize method for IE11, it fails to parse "0001-01-01T00:00:00.000Z" dates and returns Invalid Date/null.

Example code:

class MyObject {
	@autoserialize public name: string;
	@autoserializeAs(Date) public created: Date;
	@autoserializeAs(Date) public modified: Date;
}

let myObject = new MyObject();
myObject.name = 'TEST';
myObject.created = new Date('0001-01-01T00:00:00.000Z');
myObject.modified = new Date('2017-01-01T00:00:00.000Z');

let clone = Deserialize(myObject, MyObject) as MyObject;

console.log(JSON.stringify(myObject));
console.log(JSON.stringify(clone));

And here is the output for IE11:

{"name":"TEST","created":"0001-01-01T00:00:00.000Z","modified":"2017-01-01T00:00:00.000Z"}
{"name":"TEST","created":null,"modified":"2017-01-01T00:00:00.000Z"}

Using Chrome 60, Firefox 54 and Microsoft Edge 41, this works just fine:

{"name":"TEST","created":"0001-01-01T00:00:00.000Z","modified":"2017-01-01T00:00:00.000Z"}
{"name":"TEST","created":"0001-01-01T00:00:00.000Z","modified":"2017-01-01T00:00:00.000Z"}

Using only @autoserialize works for IE11, but that is not a workable solution.

Factories/callbacks for serialization and deserialization

Hi,
Thanks for you great work on this library. One problem I have at the moment is that I want to be able to instantiate objects ( new Class() ) from a factory not using the standard object creation. I can also think of scenarios where it would be good to hook into the deserialization step, rather than relying on JSON.stringify.

Any chance you could add these hooks in? I was thinking of passing a function to the decorators for the particular fields, which would optionally be used for object creation or deserialization.

I would create a PR for this but my current employer does not allow contributing to OS projects (go figure!?!!).

Regards,
John

Ability to add space between serialized properties

Hi,
Thanks for your wonderful contribution to typescript.

Request|
Given JSON.stringify(Serialize(instance), the result is a single string without any white space.
For readability, I was wondering if there could be an optional flag to input a space (or any charcter) between the properties.

For example,
JSON.stringify(Serialize(this.name) results in : {"title":"Tom","first":"Tavin","last":"Foo","middle":"Seymour","suffix":"","isValid":true}.

I would like to generate the following instead
{"title": "Tom", "first": "Tavin", "last": "Foo", "middle": "Seymour", "suffix": "", "isValid": true} (note the spaces after each comma and between the semicolon and and its corrresponding value..

Let me know what you think.
Thanks

Support type parameterized `Deserialize` function

I am writing Dserializable abstract class which indicate it can be deserialized and has deserialize Function. It looks like

const cerialize = require('cerialize'); // import

abstract class Deserializable {
  public static deserialize<T> (json, constructor): T {
    return cerialize.Deserialize(json, constructor);
  }
}

// usage
class Command extends Deserializable {
  @deserialize public help: boolean;
  @deserializeAs(CommandOrder, "_order") public orders: Array<CommandOrder>;
  @deserializeAs("_args") public args: Array<String>;
}

let cmd = Command.deserialize<Command>(json, Command);

But since cerialize.Deserialize requires the constructor function as the second arg, It's somewhat verbose.

If we have a type parameterized cerialize.Deserialize function, we can make more simplified Deserialzable. For example,

export abstract class Deserializable {
  public static deserialize<T> (json): T {
    return Deserialize<T>(json);
  }
}

// more simple
Command.deserialize<Command>(json);

Thanks. :)

Error: decorator is not a function

When I try to use the @deserializeAs(Type) it fails with the error:

decorator is not a function

Code:

export class User {
    @deserialize id: string;
    @deserialize firstName: string;
    @deserialize lastName: string;
    @deserializeAs(Address) address: Address;

    displayName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

export class Address {
    @deserialize city: string;
    @deserialize country: string;
}

Any ideas?

Date format

Is there any way to choose the serialized date format ?
I'm using a NoSQL database for storage and I would like the dates to be stored in the string ISO format "2016-07-21T15:54:59.928Z".
When using cerialize, I have something like "Tue Jul 26 2016 09:54:56 GMT+0200 (Romance Daylight Time)"

Thank you

Deserializing a Map<string, MyClass> with custom serialization type doesn't instantiate the class

Hi, in fact this issue is related to #32. As you suggested, I can use a custom serialization type instead of defining the OnSerialize and Ondeserialize callbacks everytime. However, the actual class to be instantiated and set into the Map is lost, I now get a Map<string, Object>.

Do you know how can I get my actual class to be correctly instantiated?

Probably my first approach (to define the callbacks everytime) may be the only solution by now, but reusing your idea just for the serialization part, for the deserialization I would need to do it in the callback. Something like this:

// on my class
class MyClass {
    @serializeAs(StringMap)   // just for serialization
    myMap : Map<string, AnotherClass>();
}

// custom deserialization to get the correct instance of the class
// to be added in every class containing a Map<string, AnyClass>
public static OnDeserialized(instance:MyClass, json:any):void {
    let items:Object = json.items;
    instance.items = new Map<string, AnyClass>();
   Object.keys(items).forEach((key:string) => {
    let instantiatedItem:AnyClass= Deserialize(items[key], AnyClass);
    instance.items.set(key, instantiatedItem);
   });
}

// generic custom serialization type
const StringMap:Object = {
    Serialize: (map:Map<string, any>):any => {
        let obj:Object = {};
        map.forEach((value:any, key:string) => {
            obj[key] = Serialize(value);
        });
        return obj;
    }
};

License file

Thank you for the great work!
Could you add a license file for the project?

@xxxIndexable annotations don't support ES6 Maps

Currently, the @ @xxxIndexable annotations allow the user to work with simple objects to be used as a dictionary in the way {[idx : string] : SomeClass} , which is basically what the Maps in ES6 are. However, such Maps are not yet supported by these annotations.

Is it possible to have ES6 Maps supported?

small typo in README.md

1. Section: Details

class Pet {
  //keys can be customized using serializeAs(string)
  @serializeAs('Name') public name : string;
  @serialize animalType : string;

  constructor(name : string, type : string) {
    this.name = name;
    this.type /* typo */ = type;
  }

  ...

should be

class Pet {
  ...

  constructor(name : string, animalType : string) {
    this.name = name;
    this.animalType = animalType;
  }

 ...

2. Section: Deserializing Into New Instances

...

var json = {
  species: 'Oak',
  barkType: { roughness: 1 },
  leafs: [ {color: 'red', blooming: 'false', /* typo */  bloomedAt: 'Mon Dec 07 2015 11:48:20 GMT-0500 (EST)' } ]
}

...

should be

var json = {
  species: 'Oak',
  barkType: { roughness: 1 },
  leafs: [ {color: 'red', blooming: false, bloomedAt: 'Mon Dec 07 2015 11:48:20 GMT-0500 (EST)' } ]
}

Thanks for a great serialization library :)

Avoiding constructor invocation

I'm looking to handle a case where I have a value-object style class, and the constructor performs validation against a supplied argument. To explain with an example, say I have a class that only accepts a valid looking hex string provided to its constructor:

class T1 {
    @deserialize private s : string;

    constructor(s : string) {
        if (s == null || !/^[A-Fa-f0-9]+$/.test(s)) {
            throw new Error('Valid hex string must be provided');
        }

        this.s = s;
    }
}

If I then attempt to deserialize this with:

Deserialize({s: 'a3ed18c'}, T1);

I will get:

Error: Valid hex string must be provided

This is seemingly because the constructor is invoked with undefined arguments. Ideally in this case, I would like the object reconstituted, but without the constructor being invoked. One thing that I'm aware of is Object.create can potentially be used to achieve this.

So I can successfully use the following:

var i = DeserializeInto({s: 'a3ed18c'}, T1, Object.create(T1.prototype));
console.log(i, '~', i instanceof T1); // T1 { s: 'a3ed18c' } '~' true

.. but with more complex cases this becomes impractical (i.e. with nesting, arrays?)

So I'm wondering if there is anything else that is possible in the current implementation that I'm missing?

If there isn't, would it be something that would be considered for inclusion? Naively I'd guess that all instances of new (<any>type)() could be replaced with Object.create((<any>type).prototype) (assuming Object.create is actually suitable). But this would create a BC break (there could be reliance on the constructor being invoked during deserialization). An options map as an additional argument could allow people to toggle this behaviour on, avoiding this problem.

autoserializeAs(Entity) does not deserialized the entity

I have an entity that contains another entity :

export class SessionEvent {
  @autoserialize id: number;
  title: string;
  editable: boolean;
  @autoserialize product: Product; 
}

I have declared functions on the product entity. When i use @autoserialize, i have the product object but he is not instanciate, and when i use @autoserializeAs(Product) or @autoserialize(Product, 'product'), i haven't object or product entity in the return of Deserialize(json, SessionEvent).

Thanks

Nested arrays are not serialized with there Type definition

If I have a model with nested arrays, the nested arrays are not serialized with there specified type:

export class FormModel{
...
    @autoserializeAs(FormControlModel, 'form_controls')
    public formControls: FormControlModel[] = [];
...
}
export class FormControlModel{
...
    @autoserializeAs('input_type')
    public inputType: string = '';
...
}

FormControlModel field inputType is serialized as 'inputType' instead of 'input_type'

"autoserializeAs" not work.

Assuming I have a "Model" folder with a following structure:

Test.Model
-- TestModel.ts
-- TestSubModel.ts
-- Index.ts
// Test.Model/TestSubModel.ts

export class TestSubModel 
{
   @autoserialize
    private test: string;
}

index.ts contain:

export * from "./TestModel";
export * from "./TestSubModel";
Another.Test.Model
- AnotherTestModel.ts
- Index.ts

There is an inconsistency in functioning in the following scenarios:

// Another.Test.Model/AnotherTestModel.ts

export class AnotherTestModel 
{
   @autoserializeAs(TestSubModel)
    private test: TestSubModel;
}

When use:

import { TestSubModel } from "../Test.Model"; The autoserializeAs not work.

import { TestSubModel } from "../Test.Model/TestSubModel"; The autoserializeAs works.

I tried to find the problem but could not identify.

Typed Arrays

I thought i remember this working. My goal is to deserialize a top level array.

let items: TopicDTO[] = GenericDeserialize<TopicDTO[]>(action.payload, TopicDTO);

This is throwing:

Error:(41, 13) TS2322:Type 'TopicDTO' is not assignable to type 'TopicDTO[]'.
  Property 'includes' is missing in type 'TopicDTO'.

Is there a way to properly deserialize a top level json array into new class instances?

OnDeserialized hook is not called when a class have no @deserialize field

Assume that we have models deserializing Github API responses like

export class GithubEvent {
  @deserializeAs("id") public event_id: string;
  @deserializeAs("type") public event_type: string;
  @deserializeAs("created_at") public created_at: string;
  public actor: string; /** actor.login */
  public repo: string; /** owner/repo_name */

  public static OnDeserialized(instance : GithubEvent, json : any) : void {
    if (!_.isEmpty(json) && !_.isEmpty(json.actor))
      instance.actor = json.actor.login;

    if (!_.isEmpty(json) && !_.isEmpty(json.repo))
      instance.repo = json.repo.name;
  }
}

@inheritSerialization(GithubEvent)
export class GithubRepositoryEvent extends GithubEvent {
  public static EVENT_TYPE = "RepositoryEvent";
}

export class GithubForkEventPayload {
  /** even if ForkEventPayload doesn't need to have action field,
   *  we need it otherwise `OnDeserialized` is not called
   */
  @deserializeAs("action") public action: string;
  public forkee_id: string;
  public forkee_name: string;
  public forkee_full_name: string;
  public forkee_url: string;
  public forkee_language: string;

  public static OnDeserialized(instance: GithubForkEventPayload, payload: any): void {
    if (_.isEmpty(payload)) return;

    if (!_.isEmpty(payload.forkee)) {
      let forkee = payload.forkee;
      instance.forkee_id = forkee.id;
      instance.forkee_name = forkee.name;
      instance.forkee_full_name = forkee.full_name;
      instance.forkee_url = forkee.html_url;
      instance.forkee_language = forkee.language;
    }
  }
}
// spec
let forkEvent1 = {
  "id": "3475819128",
  "type": "ForkEvent",
  "actor": {
    "login": "1ambda",
  },
  "repo": {
    "id": 41002005,
    "name": "weichx/cerialize",
    "url": "https://api.github.com/repos/weichx/cerialize"
  },
  "payload": {
    "forkee": {
      "id": 48599725,
      "name": "cerialize",
      "full_name": "1ambda/cerialize",
      "private": false,
      "html_url": "https://github.com/1ambda/cerialize",
      "language": "TypeScript",
    }
  },
  "created_at": "2015-12-26T04:47:20Z"
};

describe("ForkEvent", () => {
  it("should be deserialized", () => {
    let raw = forkEvent1;
    let forkEvent = GithubForkEvent.deserialize(GithubForkEvent, raw);

    expect(forkEvent.event_id).toEqual(raw.id);
    expect(forkEvent.event_type).toEqual(raw.type);
    expect(forkEvent.event_type).toEqual(GithubForkEvent.EVENT_TYPE);
    expect(forkEvent.actor).toEqual(raw.actor.login);
    expect(forkEvent.repo).toEqual(raw.repo.name);
    expect(forkEvent.created_at).toEqual(raw.created_at);

    let payload = forkEvent.payload;

   // the below tests fail if we remove `@deserialize` field in `GithubForkEvenyPayload`
    expect(payload.forkee_id).toEqual(raw.payload.forkee.id);
    expect(payload.forkee_name).toEqual(raw.payload.forkee.name);
    expect(payload.forkee_full_name).toEqual(raw.payload.forkee.full_name);
    expect(payload.forkee_url).toEqual(raw.payload.forkee.html_url);
    expect(payload.forkee_language).toEqual(raw.payload.forkee.language);
  });
});

In this case, if we remove @deserializeAs("action") public action: string; field, OnDeserialized hook in GithubForkEventPayload class will be not called because metadataArray is empty.

So I think OnDeserialized hook logic should be called before checking metadataArray in deserializeObject and desrializedObjectInto functions.

I already created PR for OnDeserialized in #15. If you don't mind, I would like to fix this bug on another PR after #15 is merged as this is the different issue.

custom deserialize function

Hi,

I'm using your library to automatically serialize and deserialize objects retrieved from back-end, and I would like to execute custom treatment before assigning the final value to the property. Is it possible to pass a function to do that ? For example, converting millisecond timestamp to second timestamp, or calculate other things with the received values.

I would like to pass a function to the decorator to be executed before the final assignation. Is-it possible ?

Thanking you in advance.

Throws Uncaught ReferenceError: exports is not defined

Excellent library and thank you for sharing with the world!

So, let me give you my config:

OS: OSX 10.12.3
Node: v6.10.0
Angular-CLI: 1.0.0

package.json dependencies node:
"dependencies": { "@angular/common": "^4.0.0", "@angular/compiler": "^4.0.0", "@angular/core": "^4.0.0", "@angular/forms": "^4.0.0", "@angular/http": "^4.0.0", "@angular/platform-browser": "^4.0.0", "@angular/platform-browser-dynamic": "^4.0.0", "@angular/router": "^4.0.0", "bootstrap": "^3.3.7", "cerialize": "^0.1.14", "core-js": "^2.4.1", "hammerjs": "^2.0.8", "jquery": "^3.2.1", "moment": "^2.18.1", "rxjs": "^5.1.0", "zone.js": "^0.8.4" },

.angular-cli.json scripts node:
"scripts": [ "../node_modules/jquery/dist/jquery.min.js", "../node_modules/bootstrap/dist/js/bootstrap.min.js", "../node_modules/moment/min/moment.min.js", "../node_modules/cerialize/dist/serialize.js" ],

tsconfig.json:
{ "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "baseUrl": "src", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2016", "dom" ] } }

tsconfig.app.json:
{ "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "baseUrl": "src", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2016", "dom" ] } }

Here is the error:
Uncaught ReferenceError: exports is not defined at eval (eval at webpackJsonp.91.module.exports (addScript.js:9), <anonymous>:11:1) at eval (<anonymous>) at webpackJsonp.91.module.exports (addScript.js:9) at Object.418 (serialize.js?eb3b:1) at __webpack_require__ (bootstrap 6f84d9fโ€ฆ:52) at Object.889 (scripts.bundle.js:65) at __webpack_require__ (bootstrap 6f84d9fโ€ฆ:52) at webpackJsonpCallback (bootstrap 6f84d9fโ€ฆ:23) at scripts.bundle.js:1

A little heavy on the detail but I wanted to provide you with my environment as best as possible. When I remove cerialize from my .angular-cli.json scripts node, the error vanishes. Did I uncover a bug or did I misconfig something? Thanks!

Object Within Array Not Deserialized/Serialized

I am unable to serialize/deserialize author nodes into Author class instances even though I can successfully serialize/deserialize the types array. I console.log the constructor of each but Author is never stdout. Did I miss something from the README?

I have the following JSON payload, truncated:

{ "types": [ { "typeName": "someinfo", "summary": "someinfo", "id": "10001", "typeRefId": "10001", "data": { "id": "test" }, "author": { "authorId": "20001", "authorName": "SomeGuy999", "created": "2013-02-04T22:44:30.652Z", "lastUpdate": "2013-02-04T22:44:30.652Z", "numDislikes": "0", "numLikes": "271" } }, { "typeName": "someinfo", "summary": "someinfo", "id": "10002", "typeRefId": "10002", "data": { "id": "test" }, "author": { "authorId": "20002", "authorName": "SomeGuy999", "created": "2013-02-04T22:44:30.652Z", "lastUpdate": "2013-02-04T22:44:30.652Z", "numDislikes": "0", "numLikes": "271" } }, { "typeName": "someinfo", "summary": "someinfo", "id": "10003", "typeRefId": "10003", "data": { "id": "test" }, "author": { "authorId": "20003", "authorName": "SomeGuy999", "created": "2013-02-04T22:44:30.652Z", "lastUpdate": "2013-02-04T22:44:30.652Z", "numDislikes": "0", "numLikes": "271" } } ] }

Here are my classes and transformers:

`
import { autoserialize, autoserializeAs, serialize, deserialize } from 'cerialize';
import * as moment from 'moment';

export const MomentTransformer = {
Serialize(value: any): string {
return value.toISOString();
},
Deserialize(json: any): any {
console.log('inside MomentTransformer.Deserialize = ' + json);
return moment(json);
}
}

export const IntTransformer = {
Serialize(value: number): string {
return '' + value;
},
Deserialize(value?: any): number {
return (value === undefined || value === null || !Number.isInteger(value)) ? 0 : parseInt(value);
}
}

export class Type {

@autoserialize public typeName: string;
@autoserialize public id: string;
@autoserialize public typeRefId: string;
@autoserialize public data: Object;
@autoserialize public summary: string;
@autoserializeAs(Author) public author: Author;

constructor(
    typeName: string,
    id: string,
    typeRefId: string,
    data: Object,
    summary: string,
    author: Author
) {
    console.log('Type');  // <= sanity check!!
}

}

export class Author {

@autoserialize public authorId: string;
@autoserialize public authorName: string;
@autoserializeAs(MomentTransformer) public created: any;
@autoserializeAs(MomentTransformer) public lastUpdate: any;
@autoserializeAs(IntTransformer) public numLikes: number;
@autoserializeAs(IntTransformer) public numDislikes: number;

constructor(
    authorId: string,
    authorName: string,
    created: any,
    lastUpdate: any,
    numLikes: number,
    numDislikes: number
) {
    console.log('Author'); // <= sanity check. Never see it!!
}

}
`

Circular Reference Handling Improvement

I noticed that when there's a circular reference in an entity, it will cause @autoSerializeAs on a child field to fail. However, this is silent. It would be great if it wasn't silent! They just come back as undefined with no feedback.

Issue on deserializeAs(Date) when Date is overwritten

Hello,

We are using sinon in our tests to fake dates.
Then, when we use cerialize to convert a json containing a string date, it doesn't return a Date object:

let fakeTimers = sinon.useFakeTimers();

class SerializeTestClass extends SerializeTestClassBase {
    @autoserializeAs(Date) public scalarDate: Date;
}
json = {
      scalarDate: (new Date(2016, 0, 1)).toISOString()
}
object = GenericDeserialize<SerializeTestClass>(json, SerializeTestClass);

then, object.scalarDate is not a Date instance as expected.

To resolve this you only have to change the way you detect the type corresponds to a date:

metadata.deserializedType === Date
should be
metadata.deserializedType === Date.prototype.constructor
(you have this 3 times)

Also:
type === Date
should be
type === Date.prototype.constructor
(you have this only once)

Again, if you want I do a pull request, feel free to ask me.

Can not deserialize Generic class

I tried using GenericDeserialize and Deserialize method in order to deserialize my generic typescript class, but it doesn't recognize any generic classes.
Example:
generic class:
export class PaginatedList<T> {
@deserializeAs(T) items:T[];
@deserialize currentPage:number;
@deserialize totalCount:number;
}
use:
Deserialize(res, PaginatedList<User>);

Anything i'm missing here or it's simply not supported?

Cannot load cerialize in angular-cli application

Hi,
I have been trying to load cerialize in an angular-cli generated application for the last two days without much success. The semantics of the directory structure are different from the seed I previously used. I have tried various forms of the following without much success

file | angular-cli-build.js

var Angular2App = require('angular-cli/lib/broccoli/angular2-app');

module.exports = function (defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist//*.+(js|js.map)',
'es6-shim/es6-shim.js',
'reflect-metadata/
/.+(js|js.map)',
'rxjs/__/
.+(js|js.map)',
'@angular//*.+(js|js.map)',
'@angular2-material/
/.js',
'angularfire2/__/
.js',
'serialize.js',
'firebase/lib/*.js',
'lodash/lodash.js'
]
};

file | system-config.ts
const map: any = {
'@angular2-material': 'vendor/@angular2-material',
'cerialize': 'vendor/cerialize/dist/serialize.js',
'lodash': 'vendor/lodash/lodash.js'
};

I cannot seem to find a way to reference the serialize.d.ts.

Thanks for your help.

Typescript 2.4 breaks support of enum

With 2.4, Typescript add some check about weak types.

See the related changelog.

If we look at the deserializeAs annotation signature

export declare function deserializeAs(keyNameOrType: string | Function | ISerializable, keyName?: string): any;

And its usage with enums

// in my.enum.ts
export enum MyEnum { foo, bar }

SerializableEnumeration(MyEnum);

// in my.model.ts
export class MyModel {

    @deserializeAs(MyEnum)
    typeEnum: MyEnum;
}

MyEnum is supposed to be an ISerializable. With SerializableEnumeration(), it is, at runtime. But at compilation type, Typescript has no idea about this extension and the new weak type checking throws.

Typescript proposes a workaround at the end of the section.

Since this is a breaking change, you may need to know about the workarounds which are the same as those for strict object literal checks:

  1. Declare the properties if they really do exist.
  2. Add an index signature to the weak type (i.e. [propName: string]: {}).
  3. Use a type assertion (i.e. opts as Options).

Deserialize array of various types

Hello, I have a problem with deserializing array of various types. This seems not to be supported, and it would be very helpful as it would enable me to use type hierarchy in serialization.

Example:

enum Type {
  B, C
}
abstract class A
{
  @autoserialize
  type: Type;
}

@inheritSerialization(A)
class B extends A
{
  @autoserialize
  str = "Hello";
}

@inheritSerialization(A)
class C extends A
{
  @autoserialize
  num = 1;
}

class X
{
  @autoserializeAs(() => [B, C])
  array = [ new B(), new C() ];
}

    console.log('=========>>> TEST START <<<==============');
    let x = new X();
    (<B> x.array[0]).type = Type.B;
    (<B> x.array[0]).str = 'LALA';
    (<C> x.array[1]).num = 123;
    (<C> x.array[1]).type = Type.C;
    let json = Serialize(x);
    console.log(json);
    let array2 = Deserialize(json, X);
    console.log(array2);
    console.log('=========>>> TEST END <<<==============');

This is just an example of what I'm trying to achieve. My point is to distinguish the type of each object in the array X.array to have different types in deserialization. So, in this example, array2.array[0] would be of type B, and array2.array[1] would be instance of class C.

Maybe you can advise some other solution, I was just playing with autoserializeAs annotation, but I was not able to find out any. Also, please note that in reality, I would like to use it to deserialize a tree with various subnodes, so the depth of the objects can be quite big.

Thank you

Generics Support?

Is there a way to work with DeserializeInto using a an Abstract Class with a Generic T:

export class BaseService {
...
.map((response) => DeserializeInto(response.json(), T);
}

I understand Typescript discards Types at runtime, which makes this non trivial. Any best practices?

Problem With Maps

I'm trying to come up with a simple example here, but the longterm goal is to create extend IStringTMap with custom type.

Long Term Goal:
class IPersonMap extends IStringTMap<Person> {};
Current Test Failure:
class IStringArrayMap extends IStringTMap<string[]> {};
Right now, this fails to deserialize.

let payload: any = {
    "alpha": ["dna", "chromatin", "core", "hmg", "particles", "nucleosome", "histones", "nucleosomes", "micrococcal", "nuclease"],
    "beta": ["cancer", "studies", "risk", "data", "lave", "analysis", "seskin", "osaka", "registry", "analyses"],
    "delta": ["dna", "sequence", "sequences", "gene", "cloned", "region", "genes", "cdna", "repeated", "coding"],
    "gamma": ["dna", "sequence", "sequences", "mitochondrial", "human", "wheat", "rrna", "rdna", "cytosine", "cell"]
}

class IStringTMap<T> { [key: string]: T; };
class IStringArrayMap extends IStringTMap<string[]> {};

let instance0:IStringArrayMap = payload;
let instanceA: IStringArrayMap = GenericDeserialize<IStringArrayMap>(payload, IStringArrayMap);

console.log( instance0["beta"] );
console.log( instanceA["beta"] );

[ 'cancer',
  'studies',
  'risk',
  'data',
  'lave',
  'analysis',
  'seskin',
  'osaka',
  'registry',
  'analyses' ]
undefined

Process finished with exit code 0

Expected:
instanceA should not be undefined.

Tests to display workflow with typescript

How am i supposed to import serialize.d.ts inside my /typings/tsd.d.ts to be able to use it inside my Typescript module?

import {Serialize, serialize} from 'cerialize';

I'm trying it currently as:

/// <reference path="../node_modules/cerialize/dist/serialize.d.ts" />

And i get an error:

Error:(1, 35) TS2307: Cannot find module 'cerialize'.

Since serialize.d.ts does not contains ambient declaration:

export module "cerialize" {  }

how to install the library

Hello there I am pretty new in typescript and javascript and I have big trouble installing your library.
I installed it with npm

npm install --save cerialize

I have the autocompletion in visual studio code and I find the library on the disk so it seems to work.
But when I load my application I have strange messages

serialize.js:10 Uncaught ReferenceError: exports is not defined
angular2-polyfills.js:126 GET http://localhost:3000/cerialize 404 (Not Found)

and the app is broken.
I added the serialize.js script in the header though.

<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
<!-- #docregion router -->
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<!-- #enddocregion router -->
<script src="node_modules/cerialize/dist/serialize.js"></script>
<script>
  System.config({packages: {app: {format: 'register', defaultExtension: 'js'}}});
  System.import('app/main')
        .then(null, console.error.bind(console));
</script>

Using google chrome. Hope you will help me

Issue on deserializeAs(String)

Hello,

I found another issue using autoserializeAs(String):

class SerializeTestClass extends SerializeTestClassBase {
    @autoserializeAs(String) public scalarString: string;
}

json = {
      scalarString: null
}
object = GenericDeserialize<SerializeTestClass>(json, SerializeTestClass);

then it results object.scalarString = 'null' (a string with null inside instead of null)

To resolve this in the libary, you only have to add in function deserializeObject

if (source === null) {
            instance[keyName] = source;
}

Do you want me to do a pull request?

Thank you.

Empty strings in version 0.1.15, is converted to null

Hello,

I have been using cerialize for a while, and I am generally very satisfied. It does have some funky behaviors that you will have to learn to use it in more advanced cases, but it is not that problematic.

However, after the latest update (0.1.15) an empty JSON string ("") is deserialized into null, which for me is a big problem. I will now have to go through my objects manually to change this back to empty string. Meaning that the value gained from using the library seems to disappear.

My solution for now is to roll back to the version 0.1.14, which also means rolling back my typescript version.

I hope that you can help me, and maybe release a new version that fixes this, or at least makes it as an option or similar.

  • Bjarke

Fails to deserialize from a plain array using Serializer

Tests: https://github.com/garkin/cerialize/commit/2dd885a6641dc0f10cb8776ecfdc1986031f5ca2

Failures:
1) autoserializeAs using Serializer to plain array data will be deserialized
1.1) Expected false to be truthy.
    Error: Expected false to be truthy.
        at stack (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1577:17)
        at buildExpectationResult (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1547:14)
        at Spec.Env.expectationResultFactory (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:638:18)
        at Spec.addExpectationResult (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:330:34)
        at Expectation.addExpectationResult (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:588:21)
        at Expectation.toBeTruthy (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1501:12)
        at Object.<anonymous> (C:\WORKSHOP\_little_games\cerialize\cerialize\spec\spec\autoserialize_annotation_spec.js:184:52)
        at attemptSync (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1886:24)
        at QueueRunner.run (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1874:9)
        at QueueRunner.execute (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1859:10)

2) autoserializeAs using Serializer to plain array data will be deserializedInto
2.1) TypeError: object is not a function
    TypeError: object is not a function
        at deserializeArrayInto (C:\WORKSHOP\_little_games\cerialize\cerialize\spec\src\serialize.js:258:81)
        at deserializeObjectInto (C:\WORKSHOP\_little_games\cerialize\cerialize\spec\src\serialize.js:300:37)
        at Object.DeserializeInto (C:\WORKSHOP\_little_games\cerialize\cerialize\spec\src\serialize.js:340:16)
        at Object.<anonymous> (C:\WORKSHOP\_little_games\cerialize\cerialize\spec\spec\autoserialize_annotation_spec.js:188:38)
        at attemptSync (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1886:24)
        at QueueRunner.run (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1874:9)
        at QueueRunner.execute (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:1859:10)
        at Spec.Env.queueRunnerFactory (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:697:35)
        at Spec.execute (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:359:10)
        at Object.fn (C:\WORKSHOP\_little_games\cerialize\cerialize\node_modules\gulp-jasmine\node_modules\jasmine\node_modules\jasmine-core\lib\jasmine-core\jasmine.js:2479:37)


70 specs, 2 failures
Finished in 0 seconds

Nested object Serialization with custom key name

Hi there,

First things first, thanks for this lib, it's really great.

I am facing a problem , did not see the same error already reported, so I am not sure either it's a new bug, known bug or my mistake but I've attached here below:

When nesting objects, they get mapped with values, that's working fine, but it doesn't get inferred the new name for the property.

The code:

class Person {
....
@autoserializeAs(Person, 'Girl_Friend')
public girlFriend: Person;

image

As you can see in the image attached, the first time girlfriend is serialized, it does work, but not in cascade. And not just the that property but the whole object pending of it, so "Created" at the first level got serialized successfully but not in cascade.

I have tried to declared the OnSerialized method within the Person class to call Serialize method recursivly, but it seems to do not affect it, it just gets hit once.

public static OnSerialized(instance: Person, json: any): void {
        if (instance.girlFriend) {
            instance.girlFriend = Serialize(json.Girl_Friend, Person);
        }
    }

Thanks in advance :)

Naming Convention between GenericDeserialize and Deserialize

I just re read the documentation and realize that i've been inverting GenericDeserialize and Deserialize.

GenericDeserialize is actually Typesafe.

Deserialize is not type safe.

While GenericDeserialize makes sense in terms of using 'Generics' - in this context i actually associated Generic to mean JSON, or Untyped.

Maybe consider renaming to TypedDeserialize or something similar.

Deserialized Object Is Empty

I have a simple user class. When I try to deserialize the json I always get an empty object back. I'm logging the json and instance in OnDeserialized. I'm not seeing any errors anywhere. Just getting this empty object back. I've tried this with @deserialize and @autoserialize. What am I missing here?

User Class

import { autoserialize, autoserializeAs } from 'cerialize';
export class User  {

  @autoserialize
  public id: number;

  @autoserialize
  public username: string;

  @autoserialize
  public firstName: string;

  @autoserialize
  public lastName: string;

  @autoserialize
  public phoneNumber: string;

  @autoserializeAs(Date)
  public lastLoginDate: Date;

  @autoserialize
  public active: boolean;

  @autoserialize
  public deactivationReasonId: number;

  @autoserialize
  public emailVerified: boolean;

  @autoserializeAs(Date)
  public createdDate: Date;

  @autoserializeAs(Date)
  public modifiedDate: Date;

  public static OnDeserialized(instance : User, json : any) : void {
    console.log("in on deserialized json " + JSON.stringify(json, undefined, 2));
    console.log("in on deserialized instance " + JSON.stringify(instance, undefined, 2));
  }

  constructor() {

  }
}

OnDeserialized Log Output

in on deserialized json {
  "id": 0,
  "createdDate": 1502225992038,
  "modifiedDate": 1502243851242,
  "username": "SomeUsername",
  "firstName": "John",
  "lastName": "Richards",
  "phoneNumber": "999999990",
  "referralCode": null,
  "lastLoginDate": 1502243851242,
  "deactivationReasonId": null,
  "active": true,
  "emailVerified": true
}

in on deserialized instance {}

Deserialization call

Deserialize(response.data, User)

I also tried a simpler example by passing in this JSON with the same result

{
id: 1
firstName: "test"
}

Mark as required

It would be great if we could have a decorator that allowed use to mark a paramater as required during serialize/deserialize/auto

This would allow us to ensure that the contract is properly met.

Cerialize broken with Typescript 2.4+

Hi there,

I've been using Cerialize for quite some time and I must say it works like a charm ;)

I have a problem though, I tried to upgrade my project to Typescript2.4 and now I get some TSC errors in the usage of @serialize, @serializeAs and @autoserializeAs annotations:

Error:(13, 18) TS2345:Argument of type 'typeof MyClass' is not assignable to parameter of type 'string | ISerializable | Serializer'.
Type 'typeof MyClass' is not assignable to type 'Serializer'.
Type 'typeof MyClass' provides no match for the signature '(value: any): any'.

and I've seen that for the @serializeIndexable also fails:

Error:(201, 33) TS2345:Argument of type 'typeof MySerializableObj' is not assignable to parameter of type 'ISerializable | Serializer'.
Type 'typeof MySerializableObj' is not assignable to type 'Serializer'.
Type 'typeof MySerializableObj' provides no match for the signature '(value: any): any'.

So this error happens with any class and even with enums as described in #61

So I guess the Cerialize typings should be adapted since there are stricter checks in TS 2.4.

Do you have an idea how this can be improved?

Cannot deserialize correctly typed arrays

I have issue on array deserialize when I use the following annotation:

class Test {
    @deserializeAs(String) public arrayOfString: Array<string>;
    @deserializeAs(Number) public arrayOfNumber: Array<number>;
}
var json = {
  arrayOfString: ['String1', 'String2'],
  arrayOfNumber: [1, 2]
}
var test = Deserialize(json, Test);

I get:
'String1,String2' in test.arrayOfString when I expected ['String1', 'String2']
NaN in test.arrayOfNumber when I expected [1, 2]

When I use the following annotation, it works fine:

class Test {
    @deserialize public arrayOfString: Array<string>;
    @deserialize public arrayOfNumber: Array<number>;
}

The reason why I use deserializeAs instead of deserialize is to make your library take care to the type conversion.

Is there a way I can use your library to manage this?

Regards,

lodash dependency

/Users/jmurphy/projects/ubq/api/node_modules/@types/lodash/index.d.ts
Error:(19449, 15) TS2428:All declarations of 'WeakMap' must have identical type parameters.

I'm fairly confident this is a lodash issue, but it was brought in as a dependency of cerialize.

Any advice?

mergePrimitiveObjects fails on GenericDeserializeInto

I'm attempting to use GenericDeserializeInto to merge A and B where certain fields on A have the exact same values of object B, both B has some newer fields.
Result:

Production Error:

TypeError: Cannot assign to read only property '0' of string 'base'
    at /Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:321:34
    at Array.forEach (native)
    at mergePrimitiveObjects (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:294:23)
    at /Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:308:36
    at Array.forEach (native)
    at mergePrimitiveObjects (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:294:23)
    at /Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:308:36
    at Array.forEach (native)
    at mergePrimitiveObjects (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:294:23)
    at deserializeObjectInto (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:350:16)
    at deserializeObjectInto (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:402:37)
    at DeserializeInto (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:438:16)
    at Object.GenericDeserializeInto (/Users/jmurphy/projects/ubq/api/node_modules/cerialize/dist/serialize.js:622:12)
    at ModelController.<anonymous> (/Users/jmurphy/projects/ubq/api/dist/src/ubq/controllers/models.controller.js:105:41)
    at next (native)
    at fulfilled (/Users/jmurphy/projects/ubq/api/dist/src/ubq/controllers/models.controller.js:4:58)
    at process._tickCallback (internal/process/next_tick.js:103:7)
Cannot assign to read only property '0' of string 'base'

iModelDTO = GenericDeserializeInto(req.body, DTOModel, iModelDTO);

Test Harness Error:

let payload: any = { items: {
    "alpha": ["dna", "chromatin", "core", "hmg", "particles", "nucleosome", "histones", "nucleosomes", "micrococcal", "nuclease"],
    "beta": ["cancer", "studies", "risk", "data", "lave", "analysis", "seskin", "osaka", "registry", "analyses"],
    "delta": ["dna", "sequence", "sequences", "gene", "cloned", "region", "genes", "cdna", "repeated", "coding"],
    "gama": ["dna", "sequence", "sequences", "mitochondrial", "human", "wheat", "rrna", "rdna", "cytosine", "cell"]
} };

class IStringTMap<T> { [key: string]: T; };
class IStringMapStringArray extends IStringTMap<string[]> {};

class Airport {
  @autoserialize items: IStringMapStringArray;
}

let lax: Airport = GenericDeserialize<Airport>(payload, Airport);
let san: Airport = GenericDeserializeInto<Airport>(payload, Airport, lax);

console.log( lax );
console.log( san );
TypeError: Cannot assign to read only property '0' of string 'dna'
    at /Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:321:34
    at Array.forEach (native)
    at mergePrimitiveObjects (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:294:23)
    at /Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:308:36
    at Array.forEach (native)
    at mergePrimitiveObjects (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:294:23)
    at deserializeObjectInto (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:350:16)
    at deserializeObjectInto (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:402:37)
    at DeserializeInto (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:438:16)
    at Object.GenericDeserializeInto (/Users/jmurphy/projects/test_harness/node_modules/cerialize/dist/serialize.js:622:12)

Process finished with exit code 1

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.