0

Consider following class in JavaScript:

Tools.UserBase = Tools.Class.define("Tools.UserBase", Tools.EntityBase, {
    UserId: { type: System.Int32, key: true, computed: true },
    IsActive: { type: System.Boolean },
    IsAdmin: { type: System.Boolean },
    UserName: { type: System.String },
    UserToken: { type: System.Guid },
    init: function () {
        Tools.EntityBase.call(this, arguments);
    },
    onEndEdit: function () {

        if (this.IsActive == false && this.IsAdmin == true) {
            throw new Error("Can't disable admin user");
        }

        this.parentClass.onEndEdit();    
    }
});

When I execute this code:

var user = new Tools.UserBase()

I'll get following results:

    UserBase {
    IsActive: false
    IsAdmin: false
    UserId: 0
    UserName: ""
    UserToken: "00000000-0000-0000-0000-000000000000"
    __BackingField__IsActive: false
    __BackingField__IsAdmin: false
    __BackingField__UserId: 0
    __BackingField__UserName: ""
    __BackingField__UserToken: "00000000-0000-0000-0000-000000000000"
    __proto__: PrototypeConstructor    }

Then I use following command to create json from user object.

JSON.stringify(user)

And I get following results:

""__BackingField__UserId":0,"__BackingField__IsActive":false,"__BackingField__IsAdmin":false,"__BackingField__UserName":"","__BackingField__UserToken":"00000000-0000-0000-0000-000000000000"}"

As you can see it serialize my object with its fields instead of its properties.

And I've no control on serialization process at all.

The deserialization process is the same, JSON.parse will create a plain object instead of typed objects. (I'm not saying that it should do what I want, I'm looking for a solution for my situation)

Is there any JavaScript library which fits my needs? as like as Newtonsoft in .NET ?

Thanks in advance.

shaochuancs
  • 15,342
  • 3
  • 54
  • 62
Yaser Moradi
  • 3,267
  • 3
  • 24
  • 50
  • 2
    What is that `Tools.Class.define` (link / paste it); and how does it differentiate between "fields" and "properties"? – Bergi Jan 22 '14 at 16:20
  • @Bergi There's no specific code in Class.define method, it's all about prototype inheritance. Properties are defined by Object.defineProperty and fields are backing data storage of them, for example IsActive property has equivalent field named '__BackingField__IsActive'. I'v managed to serialize properties instead of fields with usage of toJSON method that you've mentioned before. But I want to have something like this JSON.parse(jsonStr , Person) and it creates a new person for me instead of plain object. with some extensibility features as like as Newtonsoft features. – Yaser Moradi Jan 23 '14 at 07:55
  • With your help, serialization and deserialization processes are now compatible with my classes. Thanks. I'm going to put them in my blog to provide a simple development based on OOP in javascript. – Yaser Moradi Jan 23 '14 at 08:03
  • Still the code would've been interesting. `JSON.stringify` does only consider *own* and *enumerable* properties of objects. If you're doing `Object.defineProperty` magic on the prototype, it can easily happen that they're not included… I'm looking forward for your blog article, please post a link :-) – Bergi Jan 23 '14 at 14:01

2 Answers2

1

And I've no control on serialization process at all.

Yes you do. Give you class a toJSON method that returns an object with the expected properties and it will be recognized by JSON.stringify.

The deserialization process is the same, JSON.parse will create a plain object instead of typed objects.

Because JSON does represent plain objects, that is only natural :-) Still, you can pass a reviver function to JSON.parse, which can manipulate the returned objects and exchange them for class instances. For convenience, add a (static) fromJSON function to your class that you can use in the reviver.

Is there any JavaScript library which fits my needs?

Most MVC JavaScript libraries have built-in serialisation/deserialisation methods for their models. You can either use one of them or get inspired by their code to extend your Tools.Class suite.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

But I want to have something like this JSON.parse(jsonStr , Person) and it creates a new person for me instead of plain object.

I've made an npm module named esserializer to solve this problem: save JavaScript class instance values during serialization, in plain JSON format, together with its class name information:

const ESSerializer = require('esserializer');
const serializedText = ESSerializer.serialize(anInstanceOfClassPerson);

Later on, during the deserialization stage (possibly on another machine), esserializer can recursively deserialize object instance, with all Class/Property/Method information retained, using the same class definition:

const deserializedObj = ESSerializer.deserialize(serializedText, [Person]);
// deserializedObj is a perfect copy of anInstanceOfClassPerson
shaochuancs
  • 15,342
  • 3
  • 54
  • 62