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

2
  • 2
    What's wrong with JSON.stringify? Commented Feb 11, 2014 at 14:20
  • I will clarify my question. thanks Commented Feb 11, 2014 at 14:21

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

didn't know about replacer/reviver. Thanks!
One question: in the JSON.stringify part, shouldn't I only add a __type property for non-primitive types?
that make sense.. in the case of Date I'm not sure how to deal with that, I know there was another json library (maybe json3) able to serialize Dates too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.