2010-09-10 8 views
18

Ich bin Suche nach einer Lösung zur Serialisierung (und unserialize) Javascript-Objekte in einen String in allen Browsern, einschließlich der Mitglieder des Objekts, das Funktionen sein passieren. Ein typisches Objekt wird wie folgt aussehen:Javascript: stringify Objekt (einschließlich der Mitglieder der Typ-Funktion)

{ 
    color: 'red', 
    doSomething: function (arg) { 
     alert('Do someting called with ' + arg); 
    } 
} 

doSomething() nur lokale Variablen enthalten (keine Notwendigkeit, auch die Berufung Kontext serialisiert!).

JSON.stringify() wird das ‚doSomething‘ Mitglied ignorieren, weil es eine Funktion ist. Ich weiß, dass die toSource() Methode tun wird, was ich will, aber es ist FF spezifisch.

+1

werde ich einen Kommentar hinterlassen, nur weil ich eine vollständige Lösung nicht anbietet. Eine Sache, die helfen kann, ist, dass Sie eine Funktion mit einem Aufruf von 'toString()' stringifizieren können. http://jsfiddle.net/HFMaz/ Nicht sicher über die browserübergreifende Unterstützung. – user113716

+1

Dies wird regelmäßig gefragt, aber ich kann nichts relevantes finden: \ Warum müssen Sie die Funktion trotzdem serialisieren? Vielleicht gibt es eine bessere Möglichkeit, Ihren Code zu ordnen? – lincolnk

+0

Dies ist für WYSIWYG-Projekt. Jedes Javascript-Objekt (mit Methoden) definiert das Verhalten von Seitenkomponenten. Der Seiteninhalt (einschließlich des JS-Verhaltens) muss serverseitig gespeichert und somit serialisiert werden. –

Antwort

5

Eine schnelle und schmutzige Art und Weise so sein würde:

Object.prototype.toJSON = function() { 
    var sobj = {}, i; 
    for (i in this) 
    if (this.hasOwnProperty(i)) 
     sobj[i] = typeof this[i] == 'function' ? 
     this[i].toString() : this[i]; 

return sobj; 

}; 

Offensichtlich ist dies die Serialisierung jedes Objekt in Ihrem Code auswirken wird, und könnte niave Code mit ungefilterten for in Schleifen stolpern. Die „richtige“ Weg wäre, eine rekursive Funktion zu schreiben, die die toJSON Funktion auf allen Nachkomme Mitglieder eines bestimmten Objekts hinzufügen würde, die sich mit zirkulären Referenzen und so. Unter der Annahme von single-threaded Javascript (keine Web Workers) sollte diese Methode jedoch funktionieren und keine unbeabsichtigten Nebenwirkungen erzeugen. Objekt außer Kraft zu setzen, indem eine Anordnung zurückkehrt und nicht ein Objekt

muss eine ähnliche Funktion wie Array Prototyp hinzugefügt werden. Eine andere Option wäre, eine einzelne anzuhängen und sie selektiv ein Array oder ein Objekt zurückgeben zu lassen, abhängig von der Eigenart der Objekte, aber wahrscheinlich langsamer.

function JSONstringifyWithFuncs(obj) { 
    Object.prototype.toJSON = function() { 
    var sobj = {}, i; 
    for (i in this) 
     if (this.hasOwnProperty(i)) 
     sobj[i] = typeof this[i] == 'function' ? 
      this[i].toString() : this[i]; 

    return sobj; 
    }; 
    Array.prototype.toJSON = function() { 
     var sarr = [], i; 
     for (i = 0 ; i < this.length; i++) 
      sarr.push(typeof this[i] == 'function' ? this[i].toString() : this[i]); 

     return sarr; 
    }; 

    var str = JSON.stringify(obj); 

    delete Object.prototype.toJSON; 
    delete Array.prototype.toJSON; 

    return str; 
} 

http://jsbin.com/yerumateno/2/edit

+1

Großartig, außer Arrays werden nicht mehr als Arrays serialisiert. – Adaptabi

+3

Wie würde die Syntaxanalyse aussehen? Alle Funktionen sind in Strings, also müssen wir sie in Funktionen konvertieren. – Justin

0

So etwas ...

(function(o) { 
    var s = ""; 
    for (var x in o) { 
     s += x + ": " + o[x] + "\n"; 
    } 
    return s; 
})(obj) 

Hinweis: Dies ist ein Ausdruck. Sie gibt eine String-Repräsentation des Objekts zurück, das als Argument übergeben wird (in meinem Beispiel übergebe ich das in einer Variablen namens obj).

Sie können auch die toString Methode des Prototyps des Objekts außer Kraft setzen:

Object.prototype.toString = function() { 
    // define what string you want to return when toString is called on objects 
} 
1

Es ist unmöglich, ohne die Hilfe des Objekts selbst. Zum Beispiel, wie würden Sie das Ergebnis dieses Ausdrucks serialisieren?

 
(function() { 
    var x; 
    return { 
     get: function() { return x; }, 
     set: function (y) { return x = y; } 
    }; 
})(); 

Wenn Sie nur den Text der Funktion übernehmen, dann, wenn Sie deserialisieren, wird x auf die globale Variable beziehen, nicht ein in einem Verschluss. Wenn Sie Ihre Funktion über den Browser-Status schließen (z. B. einen Verweis auf ein div-Element), müssen Sie darüber nachdenken, was Sie darunter verstehen möchten.

Sie können natürlich Ihre eigenen Methoden spezifisch für einzelne Objekte schreiben, die kodieren, was Semantik Sie Verweise zu haben, um andere Objekte wollen.

5

können Sie JSON.stringify Verwendung mit einem replacer wie:

JSON.stringify({ 
    color: 'red', 
    doSomething: function (arg) { 
     alert('Do someting called with ' + arg); 
    } 
}, function(key, val) { 
     return (typeof val === 'function') ? '' + val : val; 
}); 
+2

Ich endete mit 'JSON.stringify (myObject, Funktion (Schlüssel, val) {Rückkehr (typeof val === 'Funktion')? '[Funktion]': val;}, 4);' und es gibt wirklich nett aus . –

Verwandte Themen