Ortak nesne referanslari iceren nesneyi serialize etmek (JavaScript)
Ceviz Viki, özgür ansiklopedi
JavaScript nesnesini JSON benzeri bir sekilde yazdirir. Ortak kullanilan nesne referanslarini da goz onunde bulundurur.
Ne ise yaradigi hakkinda bir ornek:
var obj = {};
obj.array = [{a:10}, [], true, false, null, undefined, 7, 3.141, "'\"\r\n\t\b\fabc"];
obj.array_tekrar = obj.array;
obj.kendisi = obj;
obj.array_ilk = obj.array[0];
obj.array_ikinci = obj.array[1];
obj.array_ucuncu = obj.array[2];
var s = serialize(obj);
var yeni = deserialize(s);
alert(yeni == obj); // false
alert(yeni.array[7]); // 3.141
alert(yeni.array == yeni.array_tekrar); // true
alert(yeni.kendisi == yeni); // true
alert(yeni.array_ilk == yeni.array[0]); // true
alert(yeni.array_ikinci == yeni.array[1]); // true
alert(s);
/* Ciktisi:
{
"array": [
{
"a": 10
},
[],
true,
false,
null,
undefined,
7,
3.141,
"'\"\r\n\t\b\fabc"
],
"array_tekrar": { _root_: [ "array" ] },
"kendisi": { _root_: [ ] },
"array_ilk": { _root_: [ "array", 0 ] },
"array_ikinci": { _root_: [ "array", 1 ] },
"array_ucuncu": true
}
*/
Ve kod:
//============================================================================//
// JavaScript object de/serialization with shared object references. //
// //
// author: Mehmet Yavuz Selim Soyturk //
// e-mail: Mehmet dot Yavuz dot Selim at gmail dot com //
//============================================================================//
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
// //
//============================================================================//
Array.prototype.findIf = function(predicate) {
for(var i in this) {
if (predicate(this[i]))
return i;
}
return -1;
};
Array.prototype.map = function(func) {
var len = this.length;
var result = [];
for (var i=0; i<len; i++) {
result[i] = func(this[i]);
}
return result;
};
Array.prototype.appended = function(value) {
var copy = this.slice(0);
copy[copy.length] = value;
return copy;
};
//============================================================================//
// SERIALIZATION //
//============================================================================//
function indented(n) {
var s = '';
for(var i=0; i<n; i++) s += ' ';
return s;
}
function escape_string(str) {
str = str .replace( new RegExp('\\\\', 'g') , '\\\\' )
.replace( new RegExp('"', 'g') , '\\"' )
.replace( new RegExp('/', 'g') , '\\/' )
.replace( new RegExp('\b', 'g') , '\\b' )
.replace( new RegExp('\f', 'g') , '\\f' )
.replace( new RegExp('\n', 'g') , '\\n' )
.replace( new RegExp('\r', 'g') , '\\r' )
.replace( new RegExp('\t', 'g') , '\\t' );
return str;
}
function serializePrimitive(value) {
if (typeof value == 'string')
return '"' + escape_string(value) + '"';
else
return '' + value;
}
function serializePrimitiveArray(arr) {
var s = "[ ";
s += arr.map(serializePrimitive).join(', ');
s += " ]";
return s;
}
function serializeArray(arr, seen, indices, depth) {
seen[seen.length] = {obj: arr, indices: indices};
if (arr.length == 0)
return '[]';
var result = '[\n';
for (var i=0; i<arr.length; i++) {
result += indented(depth + 1);
result += serializeAny(arr[i], seen, indices.appended(i), depth + 1);
result += (i == arr.length - 1) ? '' : ', ';
result += '\n';
}
result += indented(depth) + ']';
return result;
}
function serializeObject(obj, seen, indices, depth) {
seen[seen.length] = {obj: obj, indices: indices};
var properties = [];
for (var prop_name in obj) {
if (typeof obj[i] != 'function')
properties[properties.length] = prop_name;
}
if (properties.length == 0)
return '{}';
var result = '{\n';
for (var i = 0; i < properties.length; i++) {
var prop_name = properties[i];
result += indented(depth+1);
result += '"' + escape_string(prop_name) + '": ';
result += serializeAny(obj[prop_name], seen,
indices.appended(prop_name), depth + 1);
result += (i == properties.length - 1) ? '' : ', ';
result += '\n';
}
result += indented(depth) + '}';
return result;
}
function serializeAny(value, seen, indices, depth) {
var t = typeof(value);
var prevIndex;
if (t == 'function') {
throw new Error("Cannot serialize function. Keys from root: " +
serializePrimitiveArray(indices));
}
else if (t != 'object' || value == null) {
return serializePrimitive(value);
}
else if ( (prevIndex = seen.findIf
( function(obj) { return obj.obj == value } )
) >= 0) {
return '{ _root_: ' + serializePrimitiveArray(seen[prevIndex].indices) + ' }';
}
else if (value.constructor == Array) {
return serializeArray(value, seen, indices, depth);
}
else {
return serializeObject(value, seen, indices, depth);
}
};
function serialize(obj) {
return serializeAny(obj, [], [], 0);
}
//============================================================================//
// DESERIALIZATION //
//============================================================================//
function followIndices(obj, indices) {
for (var i=0; i<indices.length; i++)
obj = obj[indices[i]];
return obj;
}
function replaceRootRefs(obj, root) {
if (typeof obj != 'object' || obj == null)
return;
for (var i in obj) {
var prop = obj[i];
if (typeof prop == 'object' && prop != null) {
if ('_root_' in prop)
obj[i] = followIndices(root, prop._root_);
replaceRootRefs(prop, root);
}
}
}
function deserialize(str) {
var obj = eval( '(' + str + ')' );
if (str.indexOf('_root_') < 0)
return obj;
replaceRootRefs(obj, obj);
return obj;
}
