Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to serialize/unserialize objects in JavaScript?

I have many JavaScript objects in my application, something like:

function Person(age) {     this.age = age;     this.isOld = function (){         return this.age > 60;     } } // before serialize, ok var p1 = new Person(77); alert("Is old: " + p1.isOld());  // after, got error Object #<Object> has no method 'isOld' var serialize = JSON.stringify(p1); var _p1 = JSON.parse(serialize); alert("Is old: " + _p1.isOld()); 

See in JS Fiddle.

My question is: is there a best practice/pattern/tip to recover my object in same type it was before serialization (instances of class Person, in this case)?

Requirements that I have:

  • Optimize disk usage: I have a big tree of objects in memory. So, I don't want to store functions.
  • Solution can use jQuery and another library to serialize/unserialize.
like image 943
Topera Avatar asked Jun 27 '11 00:06

Topera


People also ask

What is serializing in JavaScript?

The process whereby an object or data structure is translated into a format suitable for transfer over a network, or storage (e.g. in an array buffer or file format). In JavaScript, for example, you can serialize an object to a JSON string by calling the function JSON. stringify() .

Which data serialization format can JavaScript parse natively?

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It's easy for humans to read and write; it's easy for machines to parse and generate.

Why do we need to serialize objects in JavaScript?

Serialization converts an in-memory data structure to a value that can be stored or transferred. The above isn't something that can be easily transmitted to another machine or used by the same machine later after the program's process ends. To do this, we must serialize the data.


2 Answers

JSON has no functions as data types. You can only serialize strings, numbers, objects, arrays, and booleans (and null)

You could create your own toJson method, only passing the data that really has to be serialized:

Person.prototype.toJson = function() {     return JSON.stringify({age: this.age}); }; 

Similar for deserializing:

Person.fromJson = function(json) {     var data = JSON.parse(json); // Parsing the json string.     return new Person(data.age); }; 

The usage would be:

var serialize = p1.toJson(); var _p1 = Person.fromJson(serialize); alert("Is old: " + _p1.isOld()); 

To reduce the amount of work, you could consider to store all the data that needs to be serialized in a special "data" property for each Person instance. For example:

function Person(age) {     this.data = {         age: age     };     this.isOld = function (){         return this.data.age > 60 ? true : false;     } } 

then serializing and deserializing is merely calling JSON.stringify(this.data) and setting the data of an instance would be instance.data = JSON.parse(json).

This would keep the toJson and fromJson methods simple but you'd have to adjust your other functions.


Side note:

You should add the isOld method to the prototype of the function:

Person.prototype.isOld = function() {} 

Otherwise, every instance has it's own instance of that function which also increases memory.

like image 118
Felix Kling Avatar answered Sep 21 '22 01:09

Felix Kling


I wrote serialijse because I faced the same problem as you.

you can find it at https://github.com/erossignon/serialijse

It can be used in nodejs or in a browser and can serve to serialize and deserialize a complex set of objects from one context (nodejs) to the other (browser) or vice-versa.

var s = require("serialijse");   var assert = require("assert");   // testing serialization of a simple javascript object with date function testing_javascript_serialization_object_with_date() {      var o = {         date: new Date(),         name: "foo"     };     console.log(o.name, o.date.toISOString());      // JSON will fail as JSON doesn't preserve dates     try {         var jstr = JSON.stringify(o);         var jo = JSON.parse(jstr);         console.log(jo.name, jo.date.toISOString());     } catch (err) {         console.log(" JSON has failed to preserve Date during stringify/parse ");         console.log("  and has generated the following error message", err.message);     }     console.log("");        var str = s.serialize(o);     var so = s.deserialize(str);     console.log(" However Serialijse knows how to preserve date during serialization/deserialization :");     console.log(so.name, so.date.toISOString());     console.log(""); } testing_javascript_serialization_object_with_date();   // serializing a instance of a class function testing_javascript_serialization_instance_of_a_class() {      function Person() {         this.firstName = "Joe";         this.lastName = "Doe";         this.age = 42;     }      Person.prototype.fullName = function () {         return this.firstName + " " + this.lastName;     };       // testing serialization using  JSON.stringify/JSON.parse     var o = new Person();     console.log(o.fullName(), " age=", o.age);      try {         var jstr = JSON.stringify(o);         var jo = JSON.parse(jstr);         console.log(jo.fullName(), " age=", jo.age);      } catch (err) {         console.log(" JSON has failed to preserve the object class ");         console.log("  and has generated the following error message", err.message);     }     console.log("");      // now testing serialization using serialijse  serialize/deserialize     s.declarePersistable(Person);     var str = s.serialize(o);     var so = s.deserialize(str);      console.log(" However Serialijse knows how to preserve object classes serialization/deserialization :");     console.log(so.fullName(), " age=", so.age); } testing_javascript_serialization_instance_of_a_class();   // serializing an object with cyclic dependencies function testing_javascript_serialization_objects_with_cyclic_dependencies() {      var Mary = { name: "Mary", friends: [] };     var Bob = { name: "Bob", friends: [] };      Mary.friends.push(Bob);     Bob.friends.push(Mary);      var group = [ Mary, Bob];     console.log(group);      // testing serialization using  JSON.stringify/JSON.parse     try {         var jstr = JSON.stringify(group);         var jo = JSON.parse(jstr);         console.log(jo);      } catch (err) {         console.log(" JSON has failed to manage object with cyclic deps");         console.log("  and has generated the following error message", err.message);     }      // now testing serialization using serialijse  serialize/deserialize     var str = s.serialize(group);     var so = s.deserialize(str);     console.log(" However Serialijse knows to manage object with cyclic deps !");     console.log(so);     assert(so[0].friends[0] == so[1]); // Mary's friend is Bob } testing_javascript_serialization_objects_with_cyclic_dependencies(); 
like image 42
Etienne Avatar answered Sep 20 '22 01:09

Etienne