Using JSON.stringify in a custom class

I am trying to save an object in redis, which is an instance of a class and therefore has functions, here is an example:

function myClass(){ this._attr = "foo"; this.getAttr = function(){ return this._attr; } } 

Is there a way to store this object in redis along with functions? I tried JSON.stringify() , but only properties are saved. How to store function definitions and perform the following actions:

 var myObj = new myClass(); var stringObj = JSON.stringify(myObj); // store in redis and retreive as stringObj again var parsedObj = JSON.parse(stringObj); console.log(myObj.getAttr()); //prints foo console.log(parsedObj.getAttr()); // prints "Object has no method 'getAttr'" 

How can I get foo when calling parsedObj.getAttr() ?

Thank you in advance!

EDIT

There was a suggestion to change MyClass.prototype and save the values, but what about something like this (functions other than setter / getter):

 function myClass(){ this._attr = "foo"; this._accessCounts = 0; this.getAttr = function(){ this._accessCounts++; return this._attr; } this.getCount = function(){ return this._accessCounts; } } 

I am trying to illustrate a function that calculates something like a count or average when it is called, among other things.

+4
source share
5 answers

First, you do not define a class.

It's just an object with a property whose value is a function (all its member functions defined in the constructor will be copied when creating a new instance, so I say this is not a class.)

What will be disabled when using JSON.stringify .

Suppose you are using node.js, which uses V8, the best way is to define a real class and play a little with __proto__ . Which will work fine no matter how many properties you use in your class (as long as each property uses primitive data types.)

Here is an example:

 function MyClass(){ this._attr = "foo"; } MyClass.prototype = { getAttr: function(){ return this._attr; } }; var myClass = new MyClass(); var json = JSON.stringify(myClass); var newMyClass = JSON.parse(json); newMyClass.__proto__ = MyClass.prototype; console.log(newMyClass instanceof MyClass, newMyClass.getAttr()); 

which will output:

 true "foo" 
+9
source

No, JSON does not save functions (which would also be inefficient). Instead, use the serialization method and deserialization constructor. Example:

 function MyClass(){ this._attr = "foo"; this.getAttr = function(){ return this._attr; } } MyClass.prototype.toJSON() { return {attr: this.getAttr()}; // everything that needs to get stored }; MyClass.fromJSON = function(obj) { if (typeof obj == "string") obj = JSON.parse(obj); var instance = new MyClass; instance._attr = obj.attr; return instance; }; 
+3
source

Scanales, I had the same problem and I tried a method similar to Bergi’s recommendation to create new serialization / deserialization methods ... but found that this did not work for me because I have objects nested in objects (some deep ) If this is your case, then this is how I decided it. I wrote a base class (clsPersistableObject) from which all the objects that I wanted to save were inherited from. The base class has a method called a deserializer that passes a JSON string. This method sets the properties one by one (but does not destroy the existing methods), and then recursively defers the child object to the same one (as many times as necessary).

 deserialize: function (vstrString) { //.parse: convert JSON string to object state //Use JSON to quickly parse into temp object (does a deep restore of all properties) var tmpObject = JSON.parse(vstrString); //objZoo2.animal.move(); //Note: can't just do something like this: // CopyProperties(tmpObject, this); //because it will blindly replace the deep objects //completely...inadvertently wiping out methods on it. Instead: //1) set the properties manually/one-by-one. //2) on objects, defer to the deserialize on the child object (if it inherits clsPersistableObject) //2b) if it doesn't inherit it, it an intrinsic type, etc...just do a JSON parse. //loop through all properties var objProperty; for (objProperty in tmpObject) { //get property name and value var strPropertyName = objProperty; var strPropertyValue = tmpObject[objProperty]; //note: doing this .toString() will cause if (objProperty !== undefined) { //check type of property if (typeof strPropertyValue == "object") { //object property: call it recursively (and return that value) var strPropertyValue_AsString = JSON.stringify(strPropertyValue); //see if has a deserialize (ie inherited from clsPeristableObject) if ("deserialize" in this[objProperty]) { //yes: call it this[objProperty]["deserialize"](strPropertyValue_AsString); } else { //no: call normal JSON to deserialize this object and all below it this[objProperty] = JSON.parse(strPropertyValue_AsString); } //end else on if ("deserialize" in this[objProperty]) } else { //normal property: set it on "this" this[objProperty] = tmpObject[objProperty]; } //end else on if (typeof strPropertyValue == "object") } //end if (objProperty !== undefined) } } 
+1
source

What you get back grom JSON.stringify () is a string. The string has no methods. First you need to define this line, and then you can get the source object and its methods.

 var myObj = new myClass(); var stringObj = JSON.stringify(myObj); 

---- EDIT -----

 //Sorry use this: var getBackObj = JSON.parse(stringObj); //Not this var getBackObj = eval(stringObj); console.log(getBackObj.getAttr()); // this should work now 
0
source

It looks like you are trying to create a closed function. you can use () => {} to solve the area problem.

 function myClass(){ this._attr = "foo"; this._accessCounts = 0; this.getAttr = ()=>{ this._accessCounts++; return this._attr; } this.getCount = ()=>{ return this._accessCounts; } } 
0
source

All Articles