[译]JSON数据范式化(normalizr)
[译]JSON数据范式化(normalizr)
摘要 开发复杂的应用时,不可避免会有一些数据相互引用。建议你尽可能地把 state 范式化,不存在嵌套。把所有数据放到一个对象里,每个数据以 ID 为主键,不同数据相互引用时通过 ID 来查找。把 应用的 state 想像成数据库 。这种方法在 normalizr 文档里有详细阐述。 normalizr...
开发复杂的应用时,不可避免会有一些数据相互引用。建议你尽可能地把 state
范式化,不存在嵌套。把所有数据放到一个对象里,每个数据以 ID 为主键,不同数据相互引用时通过 ID 来查找。把 应用的 state 想像成数据库 。这种方法在 normalizr 文档里有详细阐述。
normalizr:将嵌套的JSON格式扁平化,方便被Redux利用;
目标
我们的目标是将:
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
- 数组的每个对象都糅合了三个维度 文章 、 作者
- 按照数据范式,应当将这两个维度拆分出来,两者的联系通过id关联起来即可
我们描述上述的结构: - 返回的是一个数组(array) - 数组的对象中包含另外一个schema —— user
应该比较合理的,应该是转换成:
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
},
users: {
1: {
id: 1,
name: 'Dan'
}
}
}
}
如何使用
观看示例最好的,就是官方的测试文件:https://github.com/gaearon/normalizr/blob/master/test/index.js
先引入 normalizr
:
import { normalize, Schema, arrayOf } from 'normalizr';
定义schema
:
var article = new Schema('articles'),
user = new Schema('users'),
collection = new Schema('collections'),
feedSchema,
input;
定义规则:
article.define({
author: user,
collections: arrayOf(collection)
});
collection.define({
curator: user
});
feedSchema = {
feed: arrayOf(article)
};
测试:
input = {
feed: [{
id: 1,
title: 'Some Article',
author: {
id: 3,
name: 'Mike Persson'
},
collections: [{
id: 1,
title: 'Awesome Writing',
curator: {
id: 4,
name: 'Andy Warhol'
}
}, {
id: 7,
title: 'Even Awesomer',
curator: {
id: 100,
name: 'T.S. Eliot'
}
}]
}, {
id: 2,
title: 'Other Article',
collections: [{
id: 2,
title: 'Neverhood',
curator: {
id: 120,
name: 'Ada Lovelace'
}
}],
author: {
id: 2,
name: 'Pete Hunt'
}
}]
};
Object.freeze(input);
normalize(input, feedSchema).should.eql({
result: {
feed: [1, 2]
},
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 3,
collections: [1, 7]
},
2: {
id: 2,
title: 'Other Article',
author: 2,
collections: [2]
}
},
collections: {
1: {
id: 1,
title: 'Awesome Writing',
curator: 4
},
2: {
id: 2,
title: 'Neverhood',
curator: 120
},
7: {
id: 7,
title: 'Even Awesomer',
curator: 100
}
},
users: {
2: {
id: 2,
name: 'Pete Hunt'
},
3: {
id: 3,
name: 'Mike Persson'
},
4: {
id: 4,
name: 'Andy Warhol'
},
100: {
id: 100,
name: 'T.S. Eliot'
},
120: {
id: 120,
name: 'Ada Lovelace'
}
}
}
});
优势
假定请求 /articles
返回的数据的schema如下:
articles: article*
article: {
author: user,
likers: user*
primary_collection: collection?
collections: collection*
}
collection: {
curator: user
}
如果不做范式化,store需要事��知道API的各种结构,比如UserStore
会包含很多样板代码来获取新用户,诸如下面那样:
switch (action.type) {
case ActionTypes.RECEIVE_USERS:
mergeUsers(action.rawUsers);
break;
case ActionTypes.RECEIVE_ARTICLES:
action.rawArticles.forEach(rawArticle => {
mergeUsers([rawArticle.user]);
mergeUsers(rawArticle.likers);
mergeUsers([rawArticle.primaryCollection.curator]);
rawArticle.collections.forEach(rawCollection => {
mergeUsers(rawCollection.curator);
});
});
UserStore.emitChange();
break;
}
store表示累觉不爱啊!! 每个store都要对返回的 进行各种foreach 才能获取想要的数据。
来一个范式吧:
const article = new Schema('articles');
const user = new Schema('users');
article.define({
author: user,
contributors: arrayOf(user),
meta: {
likes: arrayOf({
user: user
})
}
});
// ...
const json = getArticleArray();
const normalized = normalize(json, arrayOf(article));
经过范式整顿之后,你爱理或者不爱理,users对象总是在 action.entities.users
中:
const { action } = payload;
if (action.response && action.response.entities && action.response.entities.users) {
mergeUsers(action.response.entities.users);
UserStore.emitChange();
break;
}
更多示例(来自测试文件)
规范化单个文件
var article = new Schema('articles'),
input;
input = {
id: 1,
title: 'Some Article',
isFavorite: false
};
Object.freeze(input);
normalize(input, article).should.eql({
result: 1,
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
isFavorite: false
}
}
}
});
规范化内嵌对象,并删除额外key
有时候后端接口会返回很多额外的字段,甚至会有重复的字段;比如下方示例中 typeId
和 type.id
是重复的;注意方法中 形参key
是经过artcle.define
定义过的。
var article = new Schema('articles'),
type = new Schema('types'),
input;
// 定义内嵌规则
article.define({
type: type
});
input = {
id: 1,
title: 'Some Article',
isFavorite: false,
typeId: 1,
type: {
id: 1,
}
};
Object.freeze(input);
// assignEntity删除后端返回额外数据的
var options = {
assignEntity: function(obj, key, val) {
obj[key] = val;
delete obj[key + 'Id'];
}
};
normalize(input, article, options).should.eql({
result: 1,
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
isFavorite: false,
type: 1
}
},
types: {
1: {
id: 1
}
}
}
});
添加额外数据
和上个示例相反的是,mergeIntoEntity
用于将多份同质数据不同信息融合到一起,用于解决冲突。
下方示例中,author
和 reviewer
是同一个人,只是前者留下的联系方式是手机,后者留下的联系方式是邮箱,但无论如何都是同一个人;
此时就可以使用 mergeIntoEntity
将两份数据融合到一起;(注意这里是用 valueOf
规则 )
var author = new Schema('authors'),
input;
input = {
author: {
id: 1,
name: 'Ada Lovelace',
contact: {
phone: '555-0100'
}
},
reviewer: {
id: 1,
name: 'Ada Lovelace',
contact: {
email: 'ada@lovelace.com'
}
}
}
Object.freeze(input);
var options = {
mergeIntoEntity: function(entityA, entityB, entityKey) {
var key;
for (key in entityB) {
if (!entityB.hasOwnProperty(key)) {
continue;
}
if (!entityA.hasOwnProperty(key) || isEqual(entityA[key], entityB[key])) {
entityA[key] = entityB[key];
continue;
}
if (isObject(entityA[key]) && isObject(entityB[key])) {
merge(entityA[key], entityB[key])
continue;
}
console.warn('Unequal data!');
}
}
};
normalize(input, valuesOf(author), options).should.eql({
result: {
author: 1,
reviewer: 1
},
entities: {
authors: {
1: {
id: 1,
name: 'Ada Lovelace',
contact: {
phone: '555-0100',
email: 'ada@lovelace.com'
}
}
}
}
});
按指定的属性规范化
有时候对象没有 id
属性,或者我们并不想按 id
属性规范化,��以使用 idAttribute 指定;
下面的例子,就是使用slug
作为规范化的key:
var article = new Schema('articles', { idAttribute: 'slug' }),
input;
input = {
id: 1,
slug: 'some-article',
title: 'Some Article',
isFavorite: false
};
Object.freeze(input);
normalize(input, article).should.eql({
result: 'some-article',
entities: {
articles: {
'some-article': {
id: 1,
slug: 'some-article',
title: 'Some Article',
isFavorite: false
}
}
}
});
创建自定义的属性
有时候想自己创建一个key,虽然今天和去年创建的文章名称都是Happy
,但明显是不一样的,为了按时间区分出来,可以 使用自定义函数生成想要的key 。
function makeSlug(article) {
var posted = article.posted,
title = article.title.toLowerCase().replace(' ', '-');
return [title, posted.year, posted.month, posted.day].join('-');
}
var article = new Schema('articles', { idAttribute: makeSlug }),
input;
input = {
id: 1,
title: 'Some Article',
isFavorite: false,
posted: {
day: 12,
month: 3,
year: 1983
}
};
Object.freeze(input);
normalize(input, article).should.eql({
result: 'some-article-1983-3-12',
entities: {
articles: {
'some-article-1983-3-12': {
id: 1,
title: 'Some Article',
isFavorite: false,
posted: {
day: 12,
month: 3,
year: 1983
}
}
}
}
});
规范化数组
后端返回的数据往往是一串数组居多,此时规范化起到很大的作用,规范化的同时将数据压缩了一遍;
var article = new Schema('articles'),
input;
input = [{
id: 1,
title: 'Some Article'
}, {
id: 2,
title: 'Other Article'
}];
Object.freeze(input);
normalize(input, arrayOf(article)).should.eql({
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article'
},
2: {
id: 2,
title: 'Other Article'
}
}
}
});
抽取多个schema
上面讲的情形比较简单,只涉及抽出结果是单个schema的情形;现实中,你往往想抽象出多个schema,比如下方,我想抽离出 tutorials
(教程) 和articles
(文章)两个 schema,此时需要 通过 schemaAttribute 选项指定区分这两个 schema 的字段 :
var article = new Schema('articles'),
tutorial = new Schema('tutorials'),
articleOrTutorial = { articles: article, tutorials: tutorial },
input;
input = [{
id: 1,
type: 'articles',
title: 'Some Article'
}, {
id: 1,
type: 'tutorials',
title: 'Some Tutorial'
}];
Object.freeze(input);
normalize(input, arrayOf(articleOrTutorial, { schemaAttribute: 'type' })).should.eql({
result: [
{id: 1, schema: 'articles'},
{id: 1, schema: 'tutorials'}
],
entities: {
articles: {
1: {
id: 1,
type: 'articles',
title: 'Some Article'
}
},
tutorials: {
1: {
id: 1,
type: 'tutorials',
title: 'Some Tutorial'
}
}
}
});
这个示例中,虽然文章的id都是1,但很明显它们是不同的文章,因为一篇是普通文章,一篇是教程文章;因此要按schema维度抽离数据;
这里的 arrayOf(articleOrTutorial)
中的 articleOrTutorial
是包含多个属性的对象,这表示 input
应该是 articleOrTutorial
中的一种情况;
有时候原始数据属性 和 我们定义的有些差别,此时可以将 schemaAttribute
的值设成函数,将原始属性经过适当加工;比如原始属性是tutorial
, 而抽离出的 schema 名字为 tutorials
,相差一个s
:
function guessSchema(item) {
return item.type + 's';
}
var article = new Schema('articles'),
tutorial = new Schema('tutorials'),
articleOrTutorial = { articles: article, tutorials: tutorial },
input;
input = [{
id: 1,
type: 'article',
title: 'Some Article'
}, {
id: 1,
type: 'tutorial',
title: 'Some Tutorial'
}];
Object.freeze(input);
normalize(input, arrayOf(articleOrTutorial, { schemaAttribute: guessSchema })).should.eql({
result: [
{ id: 1, schema: 'articles' },
{ id: 1, schema: 'tutorials' }
],
entities: {
articles: {
1: {
id: 1,
type: 'article',
title: 'Some Article'
}
},
tutorials: {
1: {
id: 1,
type: 'tutorial',
title: 'Some Tutorial'
}
}
}
});
上述是数组情况,针对普通的对象也是可以的,将规则 改成 valueOf 即可:
var article = new Schema('articles'),
tutorial = new Schema('tutorials'),
articleOrTutorial = { articles: article, tutorials: tutorial },
input;
input = {
one: {
id: 1,
type: 'articles',
title: 'Some Article'
},
two: {
id: 2,
type: 'articles',
title: 'Another Article'
},
three: {
id: 1,
type: 'tutorials',
title: 'Some Tutorial'
}
};
Object.freeze(input);
normalize(input, valuesOf(articleOrTutorial, { schemaAttribute: 'type' })).should.eql({
result: {
one: {id: 1, schema: 'articles'},
two: {id: 2, schema: 'articles'},
three: {id: 1, schema: 'tutorials'}
},
entities: {
articles: {
1: {
id: 1,
type: 'articles',
title: 'Some Article'
},
2: {
id: 2,
type: 'articles',
title: 'Another Article'
}
},
tutorials: {
1: {
id: 1,
type: 'tutorials',
title: 'Some Tutorial'
}
}
}
});
schemaAttribute 是函数的情况就不列举了,和上述一致;
规范化内嵌情形
上面的对象比较简单,原本就是扁平化的;如果对象格式稍微复杂一些,比如每篇文章有多个作者的情形。此时需要使用 define 事先声明 schema 之间的层级关系:
var article = new Schema('articles'), user = new Schema('users'), input; article.define({ author: user }); input = { id: 1, title: 'Some Article', author: { id: 3, name: 'Mike Persson' } }; Object.freeze(input); normalize(input, article).should.eql({ result: 1, entities: { articles: { 1: { id: 1, title: 'Some Article', author: 3 } }, users: { 3: { id: 3, name: 'Mike Persson' } } } });
上面是不是觉得简单了?那么给你一个比较复杂的情形,万变不离其宗。我们最终想抽离出
articles
、users
以及collections
这三个 schema,所以只要定义这三个schema就行了,然后使用 define 方法声明这三个schema之间千丝万缕的关系;
最外层的feed只是属性,并不需要定义;
var article = new Schema('articles'), user = new Schema('users'), collection = new Schema('collections'), feedSchema, input; article.define({ author: user, collections: arrayOf(collection) }); collection.define({ curator: user }); feedSchema = { feed: arrayOf(article) }; input = { feed: [{ id: 1, title: 'Some Article', author: { id: 3, name: 'Mike Persson' }, collections: [{ id: 1, title: 'Awesome Writing', curator: { id: 4, name: 'Andy Warhol' } }, { id: 7, title: 'Even Awesomer', curator: { id: 100, name: 'T.S. Eliot' } }] }, { id: 2, title: 'Other Article', collections: [{ id: 2, title: 'Neverhood', curator: { id: 120, name: 'Ada Lovelace' } }], author: { id: 2, name: 'Pete Hunt' } }] }; Object.freeze(input); normalize(input, feedSchema).should.eql({ result: { feed: [1, 2] }, entities: { articles: { 1: { id: 1, title: 'Some Article', author: 3, collections: [1, 7] }, 2: { id: 2, title: 'Other Article', author: 2, collections: [2] } }, collections: { 1: { id: 1, title: 'Awesome Writing', curator: 4 }, 2: { id: 2, title: 'Neverhood', curator: 120 }, 7: { id: 7, title: 'Even Awesomer', curator: 100 } }, users: { 2: { id: 2, name: 'Pete Hunt' }, 3: { id: 3, name: 'Mike Persson' }, 4: { id: 4, name: 'Andy Warhol' }, 100: { id: 100, name: 'T.S. Eliot' }, 120: { id: 120, name: 'Ada Lovelace' } } } });
内嵌+数组倾斜
var article = new Schema('articles'), tutorial = new Schema('tutorials'), articleOrTutorial = { articles: article, tutorials: tutorial }, user = new Schema('users'), collection = new Schema('collections'), feedSchema, input; article.define({ author: user, collections: arrayOf(collection) }); tutorial.define({ author: user, collections: arrayOf(collection) }); collection.define({ curator: user }); feedSchema = { feed: arrayOf(articleOrTutorial, { schemaAttribute: 'type' }) }; input = { feed: [{ id: 1, type: 'articles', title: 'Some Article', author: { id: 3, name: 'Mike Persson' }, collections: [{ id: 1, title: 'Awesome Writing', curator: { id: 4, name: 'Andy Warhol' } }, { id: 7, title: 'Even Awesomer', curator: { id: 100, name: 'T.S. Eliot' } }] }, { id: 1, type: 'tutorials', title: 'Some Tutorial', collections: [{ id: 2, title: 'Neverhood', curator: { id: 120, name: 'Ada Lovelace' } }], author: { id: 2, name: 'Pete Hunt' } }] }; Object.freeze(input); normalize(input, feedSchema).should.eql({ result: { feed: [ { id: 1, schema: 'articles' }, { id: 1, schema: 'tutorials' } ] }, entities: { articles: { 1: { id: 1, type: 'articles', title: 'Some Article', author: 3, collections: [1, 7] } }, tutorials: { 1: { id: 1, type: 'tutorials', title: 'Some Tutorial', author: 2, collections: [2] } }, collections: { 1: { id: 1, title: 'Awesome Writing', curator: 4 }, 2: { id: 2, title: 'Neverhood', curator: 120 }, 7: { id: 7, title: 'Even Awesomer', curator: 100 } }, users: { 2: { id: 2, name: 'Pete Hunt' }, 3: { id: 3, name: 'Mike Persson' }, 4: { id: 4, name: 'Andy Warhol' }, 100: { id: 100, name: 'T.S. Eliot' }, 120: { id: 120, name: 'Ada Lovelace' } } } });
内嵌 + 对象(再内嵌)
看到下面的 valuesOf(arrayOf(user)) 了没有,它表示该属性是一个对象,对象里面各个数组值是 User对象数组;
var article = new Schema('articles'), user = new Schema('users'), feedSchema, input; article.define({ collaborators: valuesOf(arrayOf(user)) }); feedSchema = { feed: arrayOf(article), suggestions: valuesOf(arrayOf(article)) }; input = { feed: [{ id: 1, title: 'Some Article', collaborators: { authors: [{ id: 3, name: 'Mike Persson' }], reviewers: [{ id: 2, name: 'Pete Hunt' }] } }, { id: 2, title: 'Other Article', collaborators: { authors: [{ id: 2, name: 'Pete Hunt' }] } }, { id: 3, title: 'Last Article' }], suggestions: { 1: [{ id: 2, title: 'Other Article', collaborators: { authors: [{ id: 2, name: 'Pete Hunt' }] } }, { id: 3, title: 'Last Article' }] } }; Object.freeze(input); normalize(input, feedSchema).should.eql({ result: { feed: [1, 2, 3], suggestions: { 1: [2, 3] } }, entities: { articles: { 1: { id: 1, title: 'Some Article', collaborators: { authors: [3], reviewers: [2] } }, 2: { id: 2, title: 'Other Article', collaborators: { authors: [2] } }, 3: { id: 3, title: 'Last Article' } }, users: { 2: { id: 2, name: 'Pete Hunt' }, 3: { id: 3, name: 'Mike Persson' } } } });
还有更加复杂的,这次用上 valuesOf(userOrGroup, { schemaAttribute: 'type' }) 了:
var article = new Schema('articles'), user = new Schema('users'), group = new Schema('groups'), userOrGroup = { users: user, groups: group }, feedSchema, input; article.define({ collaborators: valuesOf(userOrGroup, { schemaAttribute: 'type' }) }); feedSchema = { feed: arrayOf(article), suggestions: valuesOf(arrayOf(article)) }; input = { feed: [{ id: 1, title: 'Some Article', collaborators: { author: { id: 3, type: 'users', name: 'Mike Persson' }, reviewer: { id: 2, type: 'groups', name: 'Reviewer Group' } } }, { id: 2, title: 'Other Article', collaborators: { author: { id: 2, type: 'users', name: 'Pete Hunt' } } }, { id: 3, title: 'Last Article' }], suggestions: { 1: [{ id: 2, title: 'Other Article' }, { id: 3, title: 'Last Article' }] } }; Object.freeze(input); normalize(input, feedSchema).should.eql({ result: { feed: [1, 2, 3], suggestions: { 1: [2, 3] } }, entities: { articles: { 1: { id: 1, title: 'Some Article', collaborators: { author: { id: 3, schema: 'users' }, reviewer: { id: 2, schema: 'groups' } } }, 2: { id: 2, title: 'Other Article', collaborators: { author: { id: 2, schema: 'users' } } }, 3: { id: 3, title: 'Last Article' } }, users: { 2: { id: 2, type: 'users', name: 'Pete Hunt' }, 3: { id: 3, type: 'users', name: 'Mike Persson' } }, groups: { 2: { id: 2, type: 'groups', name: 'Reviewer Group' } } } });
递归调用
比如某某人关注了另外的人,用户 写了一系列文章,该文章 被其他用户 订阅就是这种情况:
var article = new Schema('articles'), user = new Schema('users'), collection = new Schema('collections'), feedSchema, input; user.define({ articles: arrayOf(article) }); article.define({ collections: arrayOf(collection) }); collection.define({ subscribers: arrayOf(user) }); feedSchema = { feed: arrayOf(article) }; input = { feed: [{ id: 1, title: 'Some Article', collections: [{ id: 1, title: 'Awesome Writing', subscribers: [{ id: 4, name: 'Andy Warhol', articles: [{ id: 1, title: 'Some Article' }] }, { id: 100, name: 'T.S. Eliot', articles: [{ id: 1, title: 'Some Article' }] }] }, { id: 7, title: 'Even Awesomer', subscribers: [{ id: 100, name: 'T.S. Eliot', articles: [{ id: 1, title: 'Some Article' }] }] }] }] }; Object.freeze(input); normalize(input, feedSchema).should.eql({ result: { feed: [1] }, entities: { articles: { 1: { id: 1, title: 'Some Article', collections: [1, 7] } }, collections: { 1: { id: 1, title: 'Awesome Writing', subscribers: [4, 100] }, 7: { id: 7, title: 'Even Awesomer', subscribers: [100] } }, users: { 4: { id: 4, name: 'Andy Warhol', articles: [1] }, 100: { id: 100, name: 'T.S. Eliot', articles: [1] } } } });
上面还算好的,有些schema直接就递归声明了,比如 儿女和父母 的关系:
var user = new Schema('users'), input; user.define({ parent: user }); input = { id: 1, name: 'Andy Warhol', parent: { id: 7, name: 'Tom Dale', parent: { id: 4, name: 'Pete Hunt' } } }; Object.freeze(input); normalize(input, user).should.eql({ result: 1, entities: { users: { 1: { id: 1, name: 'Andy Warhol', parent: 7 }, 7: { id: 7, name: 'Tom Dale', parent: 4 }, 4: { id: 4, name: 'Pete Hunt' } } } });
自动merge属性
在一个数组里面,如果id属性一致,会自动抽取并合属性成一个:
var writer = new Schema('writers'), book = new Schema('books'), schema = arrayOf(writer), input; writer.define({ books: arrayOf(book) }); input = [{ id: 3, name: 'Jo Rowling', isBritish: true, location: { x: 100, y: 200, nested: ['hello', { world: true }] }, books: [{ id: 1, soldWell: true, name: 'Harry Potter' }] }, { id: 3, name: 'Jo Rowling', bio: 'writer', location: { x: 100, y: 200, nested: ['hello', { world: true }] }, books: [{ id: 1, isAwesome: true, name: 'Harry Potter' }] }]; normalize(input, schema).should.eql({ result: [3, 3], entities: { writers: { 3: { id: 3, isBritish: true, name: 'Jo Rowling', bio: 'writer', books: [1], location: { x: 100, y: 200, nested: ['hello', { world: true }] } } }, books: { 1: { id: 1, isAwesome: true, soldWell: true, name: 'Harry Potter' } } } });
如果合并过程中有冲突会有提示,并自动剔除冲突的属性;比如下方同一个作者写的书,一个对象里描述“卖得好”,而在另外一个对象里却描述“卖得差”,明显是有问题的:
var writer = new Schema('writers'), book = new Schema('books'), schema = arrayOf(writer), input; writer.define({ books: arrayOf(book) }); input = [{ id: 3, name: 'Jo Rowling', books: [{ id: 1, soldWell: true, name: 'Harry Potter' }] }, { id: 3, name: 'Jo Rowling', books: [{ id: 1, soldWell: false, name: 'Harry Potter' }] }]; var warnCalled = false, realConsoleWarn; function mockWarn() { warnCalled = true; } realConsoleWarn = console.warn; console.warn = mockWarn; normalize(input, schema).should.eql({ result: [3, 3], entities: { writers: { 3: { id: 3, name: 'Jo Rowling', books: [1] } }, books: { 1: { id: 1, soldWell: true, name: 'Harry Potter' } } } }); warnCalled.should.eq(true); console.warn = realConsoleWarn;
传入不存在的schema规范
如果应用的schma规范不存在,你还传入,就会创建一个新的父属性:
var writer = new Schema('writers'), schema = writer, input; input = { id: 'constructor', name: 'Constructor', isAwesome: true }; normalize(input, schema).should.eql({ result: 'constructor', entities: { writers: { constructor: { id: 'constructor', name: 'Constructor', isAwesome: true } } }
本文永久更新链接地址:
评论暂时关闭