2

For serialisation purposes, I was wondering if there is a library for converting typed objects into plain json and back.

the naive solution would be something like:

function Person( name, sex, age ) {
    this.name = name;
    this.sex = sex;
    this.age = age;
}

Person.prototype.serialize = function () {
    var obj = this;
    return '{ ' + Object.getOwnPropertyNames( this ).map( function ( key ) {
        var value = obj[key];
        if ( typeof value === 'string' ) { value = '"' + value + '"'; }
        return '"' + key + '": ' + value;
    }).join( ', ' ) + ' }';
};

Person.deserialize = function ( input ) {
    var obj = JSON.parse( input );
    return new Person( obj.name, obj.sex, obj.age );
};

(from: Javascript Serialization of Typed Objects)

Is there a simple solution for nested types?

Edit:

Suppose I have a set of Models (like backbone models): User, Task, etc. Each model supports toJson, and fromJson functions. toJson returns a plain object with the model's attributes. fromJson takes a plain object and creates a new model object.

I'm looking for a solution which can restore the types. For example by saving a '_prototype' property with the name of the original type.

Edit:

I just found this: https://stackoverflow.com/a/14028886/1163440 This is what I had in mind.. but I am looking for nested types

Community
  • 1
  • 1
Ofri
  • 474
  • 5
  • 13

1 Answers1

3

You can use the JSON.stringify with a replacer and JSON.parse with a reviver like this:

function Person (name) {
    this.name = name;
}

var p = new Person('haaa');

p.children = [new Person('haaa jr')]

var str = JSON.stringify(p, function replacer (key, value) {
    //warning this change the object. maybe use $.extend or xtend, or a deep clone library
    value.__type = value.constructor.name
    return value;
});

var parsed = JSON.parse(str, function reviver (key, value) {
    if (value.__type === 'Person') {
      var p = new Person(value.name);
      Object.getOwnPropertyNames(value).forEach(function (k) {
        p[k] = value[k];
      });
      return p;
    }
    return value;
});

console.log('is children a Person?', parsed.children[0] instanceof Person);

The serialized object will look like this:

{
  "name": "haaa",
  "children": [
    {
      "name": "haaa jr",
      "__type": "Person"
    }
  ],
  "__type": "Person"
}

Replacer and reviver are very powerful extensibility points.

José F. Romaniello
  • 13,866
  • 3
  • 36
  • 38