Hello StackOverflowers,
I'm implementing a LocalStorage system for my web application.
But my pity is that all the objects in the Model abstraction layer have to be serialized.
I am aware that functions don't get serialized when the object is converted to JSON.
I was about to use Option 1 described here. (Which is, creating a 'static' method which returns a brand new object including the functions).
However, the problem is that even the non-function members of the objects don't get converted as well.
For example at divvie.textContent = JSON.stringify( coffee );, divvie.textContent becomes "{}".
Why? What's going on?
Sample code, not my real application but the situation is much the same: Check Coffee
var coffee = new Coffee( "0001", "DE Red Coarse",
"Douwe Egberts, red & coarse grounded." );
coffee.addSugarCube( "0x0F_BROWN", "15" );
coffee.addSugarCube( "0x0C_WHITE", "12" );
var divvie = document.getElementById( "run" );
divvie.textContent = JSON.stringify( coffee );
</script>
</body>
</html>
/**
* @class This class represents a coffee.
*
* @param {String} id
* @param {String} name
* @param {String} description
* @returns {Coffee}
*/
function Coffee( id, name, description )
{
var sugarCubes = new Array();
var maxAmountOfSweetness = 0;
/**
* @returns {String}
*/
this.getId = function()
{
return id;
};
/**
* @returns {String}
*/
this.getName = function()
{
return name;
};
/**
* @returns {String}
*/
this.getDescription = function()
{
return description;
};
/**
* @param {String} sugarCubeId
* @param {Number} amountOfSweetness
*/
this.addSugarCube = function( sugarCubeId, amountOfSweetness )
{
/// First check if this sugarCube is already in our coffee.
var sugarCubeFound = false;
for( var i = 0; i < sugarCubes.length; i++ )
{
if( sugarCubes[ i ].getId() === sugarCubeId )
{
sugarCubeFound = true;
i = sugarCubes.length;
}
}
if( !sugarCubeFound )
{
/// Oh Sweet! A new sugar cube to add in our coffee!
sugarCubes.push( new SugarCube( sugarCubeId, amountOfSweetness ) );
maxAmountOfSweetness = Math.max( maxAmountOfSweetness, amountOfSweetness );
}
};
/**
* @param {String} sugarCubeId
* @returns {SugarCube}
*/
this.getSugarCube = function( sugarCubeId )
{
for( var i = 0; i < sugarCubes.length; i++ )
{
if( sugarCubes[ i ].getId() === sugarCubeId )
{
return sugarCubes[ i ];
}
}
};
/**
* @returns {Boolean} True when the amount of sugar cubes in this coffee is 1 or more,
* false when not.
*/
this.isSweet = function()
{
if( 0 < sugarCubes.length )
{
return true;
}
return false;
};
}
/**
* @class This class represents a sugar cube
*
* @param {String} id
* @param {Number} amountOfSweetness
* @returns {SugarCube}
*/
function SugarCube( id, amountOfSweetness )
{
/**
* @returns {String}
*/
this.getId = function()
{
return id;
};
/**
* @returns {Number}
*/
this.getAmountOfSweetness = function()
{
return amountOfSweetness;
};
}
The only properties on instances created by the Coffee
constructor seem to be the methods, which have no JSON representation (because they're functions). Your data is all kept as var
iables or parameters within the closures created. These are not properties and therefore again not something that JSON is designed for.
To get it working as you expect, you'll either need to write your own toJSON
method, or move your data from var
s to properties
For example, using properties
function Coffee(id, name, description) {
this.id = id;
this.name = name;
this.description = description;
this.sugarCubes = [];
this.maxAmountOfSweetness = 0;
}
// and now you could even move the methods into the prototype
Coffee.prototype = {
getId: function () {return this.id;}
// etc
};
// new Coffee() is now JSON-able
You probably used var
to "hide" the data so it was only exposed through your methods, so the other way is to add a new method which converts it to JSON, e.g.
// in Coffee
this.toJSON = function (a, b) {
var o = {
id: id,
name: name
// etc
};
return JSON.stringify(o, a, b);
};