PHP-style Serialization of JavaScript Objects
July 30th, 2006Heavily-scripted data entry forms that expand on-the-fly as the user enters new data make life easier for the user. However, it can be hell for a developer to devise a method for the representation and submission of data with arbitrary length and depth.
A logical thing to do seems to be to take an object-oriented approach to represent all client-side data as one or multiple JavaScript objects. The objects themselves could be arrays or objects with child objects and so on. Of course the objects need to be serialized in some way before they’re posted back. Now, if you’re using PHP at the back-end, you might make use one of the multitude of JSON implementations out there for posting back the data in JSON format and converting the data back to PHP objects (assuming that you want to end up with PHP objects.) JSON is pretty much native to JavaScript (clever use of the toSource method may cut it in most cases) but you need extra PHP code for deserialization.
If you want to take the opposite approach and use PHP-native serialization, then the following function will convert any complex JavaScript object into PHP-serialized string which can be converted back into PHP objects with a single call to the deserialize PHP function. The function makes use of the method for finding out the actual class names of JavaScript objects, that I’ve written about earlier.
Update: This function is now made part of the “Porting PHP to Javascript” project, spearheaded by Kevin van Zonneveld. Move over to Kevin’s blog to see an evolving version of the serialize function and many other PHP functions that have been ported to JavaScript.
/* Returns the class name of the argument or undefined if
it's not a valid JavaScript object.
*/
function getObjectClass(obj) {
if (obj && obj.constructor && obj.constructor.toString) {
var arr = obj.constructor.toString().match(
/function\s*(\w+)/);
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
}
/* Serializes the given argument, PHP-style.
The type mapping is as follows:
JavaScript Type PHP Type
--------------- --------
Number Integer or Decimal
String String
Boolean Boolean
Array Array
Object Object
undefined Null
The special JavaScript object null also becomes PHP Null.
This function may not handle associative arrays or array
objects with additional properties well. Returns false when
called with an argument that can't be represented in PHP.
*/
function phpSerialize(val) {
switch (typeof(val)) {
case "number":
if (val == NaN || val == Infinity) {
return false;
}
return (Math.floor(val) == val ? "i" : "d") + ":" +
val + ";";
case "string":
return "s:" + val.length + ":\"" + val + "\";";
case "boolean":
return "b:" + (val ? "1" : "0") + ";";
case "object":
if (val == null) {
return "N;";
} else if (val instanceof Array) {
var idxobj = { idx: -1 };
return "a:" + val.length + ":{" + val.map(
function (item) {
this.idx++;
var ser = phpSerialize(item);
return ser ?
phpSerialize(this.idx) + ser :
false;
}, idxobj).filter(
function (item) {
return item;
}).join("") + "}";
} else {
var class_name = getObjectClass(val);
if (class_name == undefined) {
return false;
}
var props = new Array();
for (var prop in val) {
var ser = phpSerialize(val[prop]);
if (ser) {
props.push(phpSerialize(prop) + ser);
}
}
return "O:" + class_name.length + ":\"" +
class_name + "\":" + props.length + ":{" +
props.join("") + "}";
}
case "undefined":
return "N;";
}
return false;
}
April 17th, 2007 at 5:03 am
Cool site, good code…..
I did similar to your code approach included deserialization of script objects two years ago.
Thank you