最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Parsing nested Records in Immutable.js - Stack Overflow

programmeradmin2浏览0评论

Suppose I have the following Records defined using Immutable.js:

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

How do I convert plain javascript object into the User record? I tried the following but it does not produce the expected output:

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

I am aware that it is possible to explicitly create the Address record:

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

But that is not solution I am looking for. Imagine you have Records nested several levels deep and want to store/retrieve the data as JSON (e.g. in database). I would like to use the actual User record structure as a schema information for recreating the nested records. Or is there a better way to represent nested and structured immutable data?

Suppose I have the following Records defined using Immutable.js:

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

How do I convert plain javascript object into the User record? I tried the following but it does not produce the expected output:

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

I am aware that it is possible to explicitly create the Address record:

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

But that is not solution I am looking for. Imagine you have Records nested several levels deep and want to store/retrieve the data as JSON (e.g. in database). I would like to use the actual User record structure as a schema information for recreating the nested records. Or is there a better way to represent nested and structured immutable data?

Share Improve this question asked Apr 21, 2015 at 5:00 dkldkl 3,9422 gold badges29 silver badges26 bronze badges 2
  • 2 You could check the reviver argument in Immutable.fromJs, see stackoverflow.com/questions/28639878/… – OlliM Commented Apr 23, 2015 at 9:25
  • 1 To make the question clearer you should state that you want new User({name: 'Foo', address: {street: 'Bar', city: 'Baz'}}).address instanceof Address to be true. – Andy Commented Dec 20, 2016 at 3:42
Add a comment  | 

2 Answers 2

Reset to default 10

The intended use of Record structure isn't to verify the structure of provided data, just to determine set of keys that are allowed and provide default values if they're not given.

So using your example, if you initialize the record without providing Address, you will get the proper Immutable.Record object for Address:

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

One hackish way to achieve what you want would be to write a wrapper on Immutable.fromJS method with custom reviver function:

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);
}

Then you can use it like this:

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

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

However if you want to have proper checking your data structures, I would recommend using Immutable.js together with some static type-checker, like http://flowtype.org/ or http://www.typescriptlang.org/

You can make User subclass the Record definition and parse address in the constructor:

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)

Output:

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)

  1. 暂无评论