テストケースをカバーするデモがあります: http://jsfiddle.net/ZFUws/。
関数 isArray (obj) { return Array.isArray(obj); }
function isObject (obj) { //detect only simple objects
return obj.__proto_ === Object.prototype;
}
function each (obj, iterator) {
for (var key in obj) if (obj.hasOwnProperty(key)) iterator(obj[key]);
}
function map (obj, iterator) {
if (Array.isArray(obj)) return obj.map(iterator);
var newObj = {};
for (var key in obj) if (obj.hasOwnProperty(key)) newObj[key] = iterator(obj[key]);
return newObj;
}
var special = {
'regexp' : {
match : function (obj) {
return obj instanceof RegExp;
},
serialize : function (obj) {
return {
$class : 'regexp',
source : obj.source,
global : obj.global,
multiline : obj.multiline,
lastIndex : obj.lastIndex,
ignoreCase : obj.ignoreCase
}
},
deserialize : function (json) {
var flags = '',
regexp;
flags += json.global ? 'g' : '';
flags += json.multiline ? 'm' : '';
flags += json.ignoreCase ? 'i' : '';
regexp = new RegExp(json.source, flags);
regexp.lastIndex = json.lastIndex
return regexp;
}
},
'function' : {
match : function (obj) {
return obj instanceof Function;
},
serialize : function (obj) {
return {
$class : 'function',
source : obj.toString()
}
},
deserialize : function (json) {
return (new Function('return ' + json.source))();
}
}
}
function toJSON (obj) {
return map(obj, function (val) {
var json;
each(special, function (desc) {
if (desc.match(val)) json = desc.serialize(val);
});
if (isArray(val) || isObject (val)) json = toJSON(val);
return json ? json : val;
});
}
function fromJSON (json) {
return map(json, function (val) {
var obj;
if (val.$class) {
obj = special[val.$class].deserialize(val);
}
if (isArray(val) || isObject (val)) obj = fromJSON(val);
return obj ? obj : val;
});
}
var obj = {
foo: 'a string',
reg: /\s+/,
num: 100,
fart: function (name) {
return name + ' farted and it sounded like pffftt';
},
Fart: function (sound) {
this.sound = sound;
}
};
var serialized = JSON.stringify(toJSON(obj)),
deserialized = fromJSON(JSON.parse(serialized));
console.log(deserialized.foo);
console.log(deserialized.num);
console.log('11 '.search(deserialized.reg));
console.log(deserialized.fart('John'));
console.log(new deserialized.Fart('pffftt').sound);