Ich kann einen JSON-String analysieren und in ein JavaScript-Objekt verwandeln. Sie können JSON.parse()
in modernen Browsern (und IE9 +) verwenden.
Das ist großartig, aber wie kann ich dieses JavaScript-Objekt in ein bestimmtes JavaScript-Objekt verwandeln (dh mit einem bestimmten Prototyp)?
Angenommen, Sie haben:
function Foo()
{
this.a = 3;
this.b = 2;
this.test = function() {return this.a*this.b;};
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse({"a":4, "b": 3});
//Something to convert fooJSON into a Foo Object
//....... (this is what I am missing)
alert(fooJSON.test() ); //Prints 12
Auch hier frage ich mich nicht, wie man eine JSON-Zeichenfolge in ein generisches JavaScript-Objekt konvertiert. Ich möchte wissen, wie man einen JSON-String in ein "Foo" -Objekt konvertiert. Das heißt, mein Objekt sollte jetzt eine Funktion 'test' und die Eigenschaften 'a' und 'b' haben.
UPDATE Nach einigen Recherchen habe ich darüber nachgedacht ...
Object.cast = function cast(rawObj, constructor)
{
var obj = new constructor();
for(var i in rawObj)
obj[i] = rawObj[i];
return obj;
}
var fooJSON = Object.cast({"a":4, "b": 3}, Foo);
Wird es funktionieren?
UPDATE Mai 2017 : Die "moderne" Art, dies zu tun, ist via Object.assign
, aber diese Funktion ist in IE 11 oder älteren Android-Browsern nicht verfügbar.
Antworten:
Die aktuellen Antworten enthalten viel handgerollten oder Bibliothekscode. Dies ist nicht erforderlich.
Verwenden Sie
JSON.parse('{"a":1}')
diese Option , um ein einfaches Objekt zu erstellen.Verwenden Sie eine der standardisierten Funktionen, um den Prototyp festzulegen:
Object.assign(new Foo, { a: 1 })
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
quelle
Object.setPrototypeOf(...)
. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…setPrototypeOf
sind Eigenschaftsbeschreibungen.Siehe ein Beispiel unten (in diesem Beispiel wird das native JSON-Objekt verwendet). Meine Änderungen sind in GROSSBUCHSTABEN kommentiert:
quelle
for (var prop in obj) {if (obj.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
for (var prop in obj) {if (this.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
. Dies setzt voraus, dass Sie erwarten, dass der Server alle Eigenschaften auffüllt. IMO sollte auch auslösen, wenn obj.hasOwnProperty () fehlschlägt ...Möchten Sie JSON-Serialisierungs- / Deserialisierungsfunktionen hinzufügen? Dann schauen
Sie sich Folgendes an : Sie möchten dies erreichen:
toJson () ist eine normale Methode.
fromJson () ist eine statische Methode.
Implementierung :
Verwendung :
Hinweis: Wenn Sie möchten , können Sie alle Eigenschaftsdefinitionen wie ändern
this.title
,this.author
usw. durchvar title
,var author
usw. und fügen Sie Getter ihnen die UML - Definition zu erreichen.quelle
toJson()
Methode - unabhängig davon, ob einzelne Eigenschaften fest codiert sind oder für jede eine verwendet - Backslash-Escape-Codes für einige Zeichen hinzufügen muss, die in jeder Zeichenfolgeeigenschaft enthalten sein können. (EinJSON.stringify()
Heutzutage würde ich verwenden, anstatt selbst an JSon () zu schreiben. Das Rad muss jetzt nicht neu erfunden werden, da alle modernen Browser es unterstützen.serializable = ['title', 'author', ...]
.JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
Ein Blog-Beitrag, den ich nützlich fand: Grundlegendes zu JavaScript-Prototypen
Sie können mit der Eigenschaft __proto__ des Objekts herumspielen.
Dadurch kann fooJSON den Foo-Prototyp erben.
Ich glaube nicht, dass dies im IE funktioniert ... zumindest nach dem, was ich gelesen habe.
quelle
__proto__
seit langem veraltet ist . Darüber hinaus wird aus Leistungsgründen nicht empfohlen, die interne Eigenschaft eines Prototyps eines bereits erstellten Objekts zu ändern (durch Festlegen__proto__
oder auf andere Weise).[[prototype]]
und es scheint in Chrome irrelevant zu sein. In Firefox ist das Aufrufen von new langsamer als die Verwendung von Prototypen, und Object.create ist am schnellsten. Ich denke, das Problem mit FF ist, dass der erste Test langsamer ist als der letzte, nur die Reihenfolge der Ausführung ist wichtig. In Chrom läuft alles fast gleich schnell. Ich meine den Zugang zu Eigentum und die Aufforderung von Methoden. Kreatin ist mit neuen schneller, aber das ist nicht so wichtig. siehe: jsperf.com/prototype-change-test-8874874/1 und: jsperf.com/prototype-changed-method-callObject.setPrototypeOf(fooJSON, Foo.prototype)
anstatt zu setzenfooJSON.__proto__
... richtig?Vermisse ich etwas in der Frage oder warum hat seit 2011 niemand mehr
reviver
Parameter erwähntJSON.parse
?Hier ist ein vereinfachter Code für eine funktionierende Lösung: https://jsfiddle.net/Ldr2utrr/
PS: Ihre Frage ist verwirrend: >> Das ist großartig, aber wie kann ich dieses JavaScript-Objekt in ein bestimmtes JavaScript-Objekt (dh mit einem bestimmten Prototyp) verwandeln? widerspricht dem Titel, in dem Sie nach dem JSON-Parsing fragen, aber der zitierte Absatz fragt nach dem Ersetzen des JS-Laufzeitobjekt-Prototyps.
quelle
Ein alternativer Ansatz könnte verwendet werden
Object.create
. Als erstes Argument übergeben Sie den Prototyp und für das zweite übergeben Sie eine Karte mit Eigenschaftsnamen an Deskriptoren:quelle
Ich mag es, dem Konstruktor ein optionales Argument hinzuzufügen und aufzurufen
Object.assign(this, obj)
und dann alle Eigenschaften zu behandeln, die Objekte oder Arrays von Objekten selbst sind:quelle
Der Vollständigkeit halber habe ich hier einen einfachen Einzeiler gefunden (ich musste nicht nach Nicht-Foo-Eigenschaften suchen):
quelle
Ich habe ein Paket namens json-dry erstellt . Es unterstützt (Zirkel-) Referenzen und auch Klasseninstanzen.
Sie müssen 2 neue Methoden in Ihrer Klasse definieren (
toDry
auf dem Prototyp undunDry
als statische Methode), die Klasse registrieren (Dry.registerClass
) und los geht's.quelle
Obwohl dies technisch nicht das ist, was Sie wollen, können Sie die Call / Apply-Methoden des Prototyps Ihres bekannten Objekts verwenden, wenn Sie vorher wissen, welchen Objekttyp Sie behandeln möchten.
Sie können dies ändern
dazu
quelle
Ich habe die Lösungen, die ich finden konnte, kombiniert und zu einer generischen Lösung kompiliert, mit der ein benutzerdefiniertes Objekt und alle seine Felder rekursiv automatisch analysiert werden können, sodass Sie nach der Deserialisierung Prototypmethoden verwenden können.
Eine Annahme ist, dass Sie ein spezielles Feld definiert haben, das den Typ in jedem Objekt angibt, das Sie automatisch anwenden möchten (
this.__type
im Beispiel).Verwendung:
Typzuweisungsfunktion (funktioniert rekursiv, um verschachtelten Objekten Typen zuzuweisen; sie durchläuft auch Arrays, um geeignete Objekte zu finden):
quelle
Die aktuell akzeptierte Antwort funktionierte bei mir nicht. Sie müssen Object.assign () ordnungsgemäß verwenden:
Sie erstellen normalerweise Objekte dieser Klasse:
Wenn Sie eine JSON-Zeichenfolge haben, die Sie in die Person-Klasse analysieren müssen, gehen Sie folgendermaßen vor:
quelle
Olivers Antworten sind sehr klar, aber wenn Sie nach einer Lösung in Angular Js suchen, habe ich ein nettes Modul namens Angular-JsClass geschrieben, das dies erleichtert. Objekte in Litaral-Notation zu definieren, ist immer schlecht, wenn Sie auf ein großes Projekt abzielen Aber sagen, dass Entwickler vor einem Problem stehen, das genau BMiner gesagt hat, wie man einen JSON zu Prototyp- oder Konstruktor-Notationsobjekten serialisiert
https://github.com/imalhasaranga/Angular-JSClass
quelle