解析 Immutable.js 中的嵌套记录
Parsing nested Records in Immutable.js
假设我使用 Immutable.js 定义了以下记录:
var Address = Immutable.Record({street: '', city: '', zip: ''});
var User = Immutable.Record({name: '', address: new Address()});
如何将纯 javascript 对象转换为用户记录?我尝试了以下但它没有产生预期的输出:
var user = new User({name: 'Foo', address: {street: 'Bar', city: 'Baz'}});
// => Record { "name": "Foo", "address": [object Object] }
我知道可以显式创建地址记录:
var user = new User({name: 'Foo', address: new Address({street: 'Bar', city: 'Baz'})});
// => Record { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } }
但这不是我正在寻找的解决方案。想象一下,您的 Records 嵌套了多个层次,并且想要 store/retrieve 数据为 JSON(例如在数据库中)。我想使用实际的用户记录结构作为重新创建嵌套记录的模式信息。或者是否有更好的方法来表示嵌套和结构化的不可变数据?
记录结构的预期用途不是验证所提供数据的结构,只是确定允许的键集并提供默认值(如果未提供)。
因此使用您的示例,如果您在不提供地址的情况下初始化记录,您将获得地址的正确 Immutable.Record 对象:
var user = new User({name: 'Foo'});
// => Record { "name": "Foo", "address": Record { "street": "", "city": "", "zip": "" } }
一个 hackish 方法来实现你想要的是在 Immutable.fromJS
方法上写一个包装器和自定义 reviver
函数:
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);
}
那么你可以这样使用它:
var user = User.fromJS({name: 'Foo', address: {street: 'Bar', city: 'Baz'}});
// => User { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } }
但是如果你想正确检查你的数据结构,我建议使用 Immutable.js 和一些静态类型检查器,比如 http://flowtype.org/ or http://www.typescriptlang.org/
您可以使 User
成为 Record
定义的子类,并在构造函数中解析 address
:
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)
输出:
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
假设我使用 Immutable.js 定义了以下记录:
var Address = Immutable.Record({street: '', city: '', zip: ''});
var User = Immutable.Record({name: '', address: new Address()});
如何将纯 javascript 对象转换为用户记录?我尝试了以下但它没有产生预期的输出:
var user = new User({name: 'Foo', address: {street: 'Bar', city: 'Baz'}});
// => Record { "name": "Foo", "address": [object Object] }
我知道可以显式创建地址记录:
var user = new User({name: 'Foo', address: new Address({street: 'Bar', city: 'Baz'})});
// => Record { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } }
但这不是我正在寻找的解决方案。想象一下,您的 Records 嵌套了多个层次,并且想要 store/retrieve 数据为 JSON(例如在数据库中)。我想使用实际的用户记录结构作为重新创建嵌套记录的模式信息。或者是否有更好的方法来表示嵌套和结构化的不可变数据?
记录结构的预期用途不是验证所提供数据的结构,只是确定允许的键集并提供默认值(如果未提供)。
因此使用您的示例,如果您在不提供地址的情况下初始化记录,您将获得地址的正确 Immutable.Record 对象:
var user = new User({name: 'Foo'});
// => Record { "name": "Foo", "address": Record { "street": "", "city": "", "zip": "" } }
一个 hackish 方法来实现你想要的是在 Immutable.fromJS
方法上写一个包装器和自定义 reviver
函数:
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);
}
那么你可以这样使用它:
var user = User.fromJS({name: 'Foo', address: {street: 'Bar', city: 'Baz'}});
// => User { "name": "Foo", "address": Record { "street": "Bar", "city": "Baz", "zip": "" } }
但是如果你想正确检查你的数据结构,我建议使用 Immutable.js 和一些静态类型检查器,比如 http://flowtype.org/ or http://www.typescriptlang.org/
您可以使 User
成为 Record
定义的子类,并在构造函数中解析 address
:
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)
输出:
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