glenatron
glenatron

Reputation: 11372

Serialize a working JavaScript object as JSON retaining only properties?

Imagine I have a typed heirarchy in JavaScript like this:

function Person( newName )
{
    this.name = name;
    this.hats = []
}
Person.prototype = {
    findHat : function( hatName ) {
        var i=0;
        for ( i; i< this.hats.length; i++ )
         {
             if ( hats[i].name === hatName ) 
             {
                 return hats[i];
             }
         }
         return { name: "no hat found" };
    }
}

function Hat( name, description ) 
{
    this.name= name;
    this.description = description;
}

Now what I would like to be able to do is create some instances...

var bob = new Person( "Bob" );
bob.hats.push( new Hat("Top Hat", "Very smart."));
bob.hats.push( new Hat("Wooly Hat", "Very warm."));

... and then serialise them in a way that gets the simple properties and records the object hierarchy but not the functions, so that I can deserialise them directly back into those types, but if - for example - I wanted to change the behaviour of findHat I could load back my stored data into the redefined Person type safely. Something like this:

"Person:{"name":"bob","hats":[Hat:{"name":"Top Hat","description":"Very smart."}, Hat:{"name":"Wooly Hat","description":"Very warm."}]}"

Obviously, this is a highly simplified model, I am dealing with a complex and potentially deep object hierarchy in real life so if I can avoid having to create any further types or to manually create serialisation and deserialisation methods on my classes, that would be ideal.

The project is entirely written with JavaScript running in the browser and I am thinking to either store the data in the local store or post it back to a server, so my assumption is that JSON is the natural way to do this, but I haven't worked with pure JSON serialisation a whole lot and it looks as though it favours anonymous types, which would make it hard for me to relate the data to the object type. Is there a simple way ( or standard library ) to get to this or do I need to set about explicitly serialising everything as appears to have been the case a few years ago?

Upvotes: 1

Views: 800

Answers (2)

fishgen
fishgen

Reputation: 71

What I don't like about the JSON.* way is, that you need to write the functions, that do the serialisation / deserialisation. I wrote a small library, that can mix the JSON together with a javascript object using it's constructor function. In your case something like this:

let person = JsonMix(data)
  .withObject(Person, "Person")
  .withObject(Hat, "Person.hats")
  .build();

https://www.npmjs.com/package/jsonmix

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075735

Both JSON.parse and JSON.stringify let you plug into what they're doing, so you can customize the serialization. Also, you can add a toJSON method to your type's prototype objects which is called to serialize them to JSON, letting you completely control the process.

JSON.stringify lets you customize the serialized result in two ways:

  1. If the object has a toJSON method, JSON.stringify uses that.

  2. It lets you specify a "replacer" function that is called for each item being serialized, in order to give you a chance to customize the serialization a bit. You could use that as an opportunity to mark the output object with the type you want it to have when it comes back in.

JSON.parse lets you specify a "reviver" function which is essentially the converse. So you could look for your special serialized type property on the raw object, and use that combined with the raw object data to create your typed object.

I went looking for an example of using these, and...er...um...happened to find my own answer to another question going into some detail. :-)

Upvotes: 1

Related Questions