2015-04-21 26 views
15

Angenommen, ich habe folgende Einträge definiert mit Immutable.js:Parsing verschachtelte Datensätze in Immutable.js

var Address = Immutable.Record({street: '', city: '', zip: ''}); 
var User = Immutable.Record({name: '', address: new Address()}); 

Wie konvertiere ich Ebene Javascript-Objekt in den Benutzerdatensatz? Ich habe versucht, die folgenden, aber es produziert nicht die erwartete Ausgabe:

var user = new User({name: 'Foo', address: {street: 'Bar', city: 'Baz'}}); 
// => Record { "name": "Foo", "address": [object Object] } 

Ich bin mir bewusst, dass es möglich ist, ausdrücklich die Adresseintrag zu erstellen:

var user = new User({name: 'Foo', address: new Address({street: 'Bar', city: 'Baz'})}); 
// => Record { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } } 

Aber das ist nicht Lösung Ich suche . Stellen Sie sich vor, Sie haben Datensätze mehrere Ebenen tief geschachtelt und möchten die Daten als JSON (z. B. in der Datenbank) speichern/abrufen. Ich möchte die tatsächliche Benutzerdatensatzstruktur als eine Schemainformation für das Neuerstellen der geschachtelten Datensätze verwenden. Oder gibt es eine bessere Möglichkeit, verschachtelte und strukturierte unveränderbare Daten darzustellen?

+2

Sie könnten das 'reviver' Argument in' Immutable.fromJs' überprüfen, siehe http://stackoverflow.com/questions/28639878/how-to-create-a-map-of-records-from-a-javascript- raw-object-with-immutable-js – OlliM

+1

Um die Frage klarer zu machen, sollten Sie angeben, dass Sie einen neuen Benutzer ({name: 'Foo', Adresse: {street: 'Bar', city: 'Baz'}}) wollen. Adresse instanceof Adresse, um wahr zu sein. – Andy

Antwort

8

Die beabsichtigte Verwendung der Record-Struktur besteht nicht darin, die Struktur der bereitgestellten Daten zu überprüfen, sondern nur die Menge der zulässigen Schlüssel zu bestimmen und Standardwerte anzugeben, wenn sie nicht angegeben sind.

Ihr Beispiel also mit, wenn Sie den Datensatz ohne Angabe von Adresse initialisieren, werden Sie das richtige Objekt Immutable.Record für Adresse erhalten:

var user = new User({name: 'Foo'}); 
// => Record { "name": "Foo", "address": Record { "street": "", "city": "", "zip": "" } } 

One hackish Art und Weise zu erreichen, was Sie würden wollen ein Wrapper auf Immutable.fromJS Methode mit benutzerdefinierten reviver Funktion schreiben:

Immutable.Record.constructor.prototype.fromJS = function(values) { 
    var that = this; 
    var nested = Immutable.fromJS(values, function(key, value){ 
    if(that.prototype[key] && that.prototype[key].constructor.prototype instanceof Immutable.Record){return that.prototype[key].constructor.fromJS(value)} 
    else { return value } 
    }); 
    return this(nested); 
} 

Dann können Sie es wie folgt verwenden:

var user = User.fromJS({name: 'Foo', address: {street: 'Bar', city: 'Baz'}}); 

// => User { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } } 

Allerdings, wenn Sie Ihre Datenstrukturen richtige haben wollen Überprüfung, würde ich mit einigen statischen Typ-Checker, wie http://flowtype.org/ oder http://www.typescriptlang.org/

+3

Eigentlich wollte ich nicht die Struktur der Daten überprüfen, sondern die Tatsache verbergen, dass die Daten, die an untergeordnete Komponenten übergeben werden, unveränderlich sind. Wenn Sie Immutable.Map an die untergeordnete Komponente übergeben, müssen Sie sich dessen bewusst sein und data.get ('foo') anstelle von data.foo verwenden. Ich versuchte, dies zu umgehen, indem ich Record verwendete, der die Objekteigenschaften definiert, so dass die Kindkomponente (die nur die Daten rendert) einfach data.foo verwenden kann, ohne sich darum zu kümmern, ob die Daten unveränderlich sind oder nicht. – dkl

+0

Das eigentliche Problem ist die automatische Deserialisierung der 'Adresse' von reinem JSON in einen' Address' Datensatz im 'User' Konstruktor. – Andy

+0

Das ist schlau. Ich mochte es sehr. Dann entdeckte ich, dass, da 'Immutable.fromJS' von unten nach oben ist (Blätter zuerst), es nicht für tief verschachtelte Strukturen verwendet werden kann :( –

6

Sie mit Immutable.js zusammen empfehlen User Unterklasse der Record Definition machen und analysieren address im Konstruktor:

import {Record} from 'immutable' 

const Address = Record({street: '', city: '', zip: ''}); 
class User extends Record({name: '', address: new Address()}) { 
    constructor({name, address} = {}) { 
    super({name, address: new Address(address)}) 
    } 
} 

const user = new User({ 
    name: 'Andy', 
    address: { 
    street: 'wherever', 
    city: 'Austin', 
    zip: 'TX' 
    } 
}) 

console.log(user) 
console.log('user.address instanceof Address:', user.address instanceof Address) 

const user2 = new User({name: 'Bob'}) 

console.log(user2) 
console.log('user2.address instanceof Address:', user2.address instanceof Address) 

Ausgang:

User { "name": "Andy", "address": Record { "street": "wherever", "city": "Austin", "zip": "TX" } } 
user.address instanceof Address: true 
User { "name": "Bob", "address": Record { "street": "", "city": "", "zip": "" } } 
user2.address instanceof Address: true 
+0

Was ist mit' List'? –

+0

@VictorQueiroz je nachdem, wo du meine, die Liste ist ('Record' enthält eine' List'? 'List' von' Record's?) Kann eine Kombination aus dieser und der 'reviver' Funktion in der obigen Antwort erwähnt werden. – Andy

Verwandte Themen