序列化器
序列化器负责格式化你的路由处理程序的响应。
应用程序序列化器将应用于每个响应。要进行特定自定义,请定义每个模型序列化器。
import { Server, RestSerializer } from 'miragejs';
new Server({
serializers: {
application: RestSerializer,
user: RestSerializer.extend({
// user-specific customizations
})
}
})
从路由处理程序返回的任何模型或集合都将通过序列化器层。模型特定序列化器将具有最高优先级,然后是应用程序序列化器,最后是默认序列化器。
Mirage 附带了三个命名序列化器
JSONAPISerializer,用于模拟与 JSON:API 兼容的 API 服务器
import { Server, JSONAPISerializer } from 'miragejs'; new Server({ serializers: { application: JSONAPISerializer } })
ActiveModelSerializer,用于模拟使用 AMS 风格响应的 Rails API
import { Server, ActiveModelSerializer } from 'miragejs'; new Server({ serializers: { application: ActiveModelSerializer } })
RestSerializer,许多通用 REST API 的良好起点
import { Server, RestSerializer } from 'miragejs'; new Server({ serializers: { application: RestSerializer } })
此外,Mirage 还有一个基本的序列化器类,你可以使用下面记录的钩子对其进行自定义
import { Server, Serializer } from 'miragejs';
new Server({
serializers: {
application: Serializer
}
})
在编写模型特定序列化器时,请记住从你的应用程序序列化器继承,这样你的模型特定类就可以使用共享逻辑
import { Server, Serializer } from 'miragejs';
const ApplicationSerializer = Serializer.extend()
new Server({
serializers: {
application: ApplicationSerializer,
blogPost: ApplicationSerializer.extend({
include: ['comments']
})
}
})
属性
schema: 对象
对 schema 实例的引用。
它有助于引用注册的 schema 信息,例如在序列化器的 include 钩子中,以包含资源的所有关联
Serializer.extend({
include(request, resource) {
return Object.keys(this.schema.associationsFor(resource.modelName));
}
})
attrs: 任何
在模型序列化器上使用此属性来列出将在你的 JSON 负载中使用的属性。
例如,如果你在数据库中有一个名为 blog-post
的模型,它看起来像
{
id: 1,
title: 'Lorem ipsum',
createdAt: '2014-01-01 10:00:00',
updatedAt: '2014-01-03 11:42:12'
}
并且你只想使用 id
和 title
,你可以写
Serializer.extend({
attrs: ['id', 'title']
});
负载将看起来像
{
id: 1,
title: 'Lorem ipsum'
}
embed: 任何
设置相关模型是否应该被嵌入或侧加载。
不适用于 JSONAPISerializer。
默认情况下,此值为 false,因此关系是侧加载的
GET /authors/1
{
author: {
id: 1,
name: 'Link',
blogPostIds: [1, 2]
},
blogPosts: [
{ id: 1, authorId: 1, title: 'Lorem' },
{ id: 2, authorId: 1, title: 'Ipsum' }
]
}
将 embed
设置为 true 将嵌入相关记录
Serializer.extend({
embed: true
});
现在响应看起来像
GET /authors/1
{
author: {
id: 1,
name: 'Link',
blogPosts: [
{ id: 1, authorId: 1, title: 'Lorem' },
{ id: 2, authorId: 1, title: 'Ipsum' }
]
}
}
include: 任何
在模型序列化器上使用此属性来指定你希望包含在你的 JSON 负载中的相关模型。(这些可以被认为是默认的服务器端包含。)
例如,如果你有一个拥有多个 blog-post
的 author
,并且你想侧加载它们,请在 include
键中指定
new Server({
models: {
author: Model.extend({
blogPosts: hasMany()
})
},
serializers: {
author: Serializer.extend({
include: ['blogPosts']
});
}
})
现在对作者请求的响应将看起来像这样
GET /authors/1
{
author: {
id: 1,
name: 'Link',
blogPostIds: [1, 2]
},
blogPosts: [
{id: 1, authorId: 1, title: 'Lorem'},
{id: 2, authorId: 1, title: 'Ipsum'}
]
}
你还可以将 include
定义为函数,以便可以动态地确定它。
例如,你可以根据 include
查询参数有条件地包含关系
// Include blog posts for a GET to /authors/1?include=blogPosts
Serializer.extend({
include: function(request) {
if (request.queryParams.include === "blogPosts") {
return ['blogPosts'];
} else {
return [];
}
}
});
JSONAPISerializer 的查询参数包含
JSONAPISerializer 支持使用 include
查询参数开箱即用地返回复合文档。
例如,如果你的应用程序发出以下请求
GET /api/authors?include=blogPosts
那么 JSONAPISerializer
将检查请求的查询参数,看到 blogPosts 关系存在,然后像在序列化器本身的 include: [] 数组中直接指定了此关系一样进行处理。
请注意,根据规范,Mirage 优先考虑 ?include 查询参数,而不是你可能在序列化器上直接指定的默认 include: [] 数组。但是,如果请求没有 ?include 查询参数,默认包含仍将生效。
还要注意,使用 include: []
数组指定的默认包含只能接受一个模型;它们不能接受指向嵌套关系的点分隔路径。
如果你想为资源设置默认的点分隔(嵌套)包含路径,你必须在路由级别通过为 request.queryParams
设置默认值来执行此操作
this.get('/users', function(schema, request) => {
request.queryParams = request.queryParams || {};
if (!request.queryParams.include) {
request.queryParams.include = 'blog-posts.comments';
}
// rest of route handler logic
});
root: 任何
设置你的 JSON 响应是否应该包含根键。
不适用于 JSONAPISerializer。
默认为 true,因此对作者的请求看起来像
GET /authors/1
{
author: {
id: 1,
name: 'Link'
}
}
将 root
设置为 false 将禁用它
Serializer.extend({
root: false
});
现在响应看起来像
GET /authors/1
{
id: 1,
name: 'Link'
}
serializeIds: 任何
使用它来定义你的序列化器如何处理序列化关系键。它可以取三个值之一
included
是默认值,如果关系与模型或集合一起包含(侧加载)在响应中,它将序列化关系的 IDalways
将始终序列化响应中模型或集合的所有关系的 IDnever
永远不会序列化模型或集合中关系的 ID
方法
keyForAttribute(attr: 任何): 任何
用于自定义在你的 JSON 负载中格式化模型属性的方式。
默认情况下,模型属性为 camelCase
GET /authors/1
{
author: {
firstName: 'Link',
lastName: 'The WoodElf'
}
}
如果你的 API 期望蛇形大小写,你可以写下以下内容
// serializers/application.js
export default Serializer.extend({
keyForAttribute(attr) {
return underscore(attr);
}
});
现在响应将看起来像
{
author: {
first_name: 'Link',
last_name: 'The WoodElf'
}
}
keyForCollection(modelName: 任何): 任何
用于在序列化主集合时自定义键。默认情况下,这会将 keyForModel
返回值的复数形式。
例如,默认情况下,以下请求可能看起来像
GET /blogPosts
{
blogPosts: [
{
id: 1,
title: 'Lorem ipsum'
},
...
]
}
如果你的 API 使用连字符来连接键,你可以覆盖 keyForCollection
// serializers/application.js
export default Serializer.extend({
keyForCollection(modelName) {
return this._container.inflector.pluralize(dasherize(modelName));
}
});
现在响应将看起来像
{
'blog-posts': [
{
id: 1,
title: 'Lorem ipsum'
},
...
]
}
keyForEmbeddedRelationship(attributeName: 任何): 任何
与 keyForRelationship
类似,但用于嵌入式关系。
keyForForeignKey(relationshipName: any): any
类似于 keyForRelationshipIds
,但适用于 belongsTo
关系。
例如,如果您要序列化一个包含一个 author
的 blogPost
,您的 blogPost
JSON 会包含一个 authorId
键
{
blogPost: {
id: 1,
authorId: 1
},
author: ...
}
覆盖 keyForForeignKey
以格式化此键
// serializers/application.js
export default Serializer.extend({
keyForForeignKey(relationshipName) {
return underscore(relationshipName) + '_id';
}
});
现在响应将类似于
{
blogPost: {
id: 1,
author_id: 1
},
author: ...
}
keyForModel(modelName: any): any
用于在序列化模型名称为 modelName 的主模型时定义自定义键。例如,默认序列化器将返回类似以下内容
GET /blogPosts/1
{
blogPost: {
id: 1,
title: 'Lorem ipsum'
}
}
如果您的 API 使用连字符键,您可以覆盖 keyForModel
// serializers/application.js
export default Serializer.extend({
keyForModel(modelName) {
return hyphenate(modelName);
}
});
现在响应将类似于
{
'blog-post': {
id: 1,
title: 'Lorem ipsum'
}
}
keyForPolymorphicForeignKeyId(relationshipName: String): String
多态关系使用类型-ID 对表示。
给定以下模型
Model.extend({
commentable: belongsTo({ polymorphic: true })
});
默认序列化器将生成
{
comment: {
id: 1,
commentableType: 'post',
commentableId: '1'
}
}
此钩子控制如何序列化 id
字段(在上面的示例中为 commentableId
)。默认情况下,它会将关系转换为驼峰式命名并添加 Id
作为后缀。
keyForPolymorphicForeignKeyType(relationshipName: String): String
多态关系使用类型-ID 对表示。
给定以下模型
Model.extend({
commentable: belongsTo({ polymorphic: true })
});
默认序列化器将生成
{
comment: {
id: 1,
commentableType: 'post',
commentableId: '1'
}
}
此钩子控制如何序列化 type
字段(在上面的示例中为 commentableType
)。默认情况下,它会将关系转换为驼峰式命名并添加 Type
作为后缀。
keyForRelationship(modelName: any): any
使用此钩子来格式化与该模型相关的集合的键。 modelName 是关系的命名参数。
例如,如果您要序列化一个包含多个 blogPosts
的 author
,默认响应将类似于
{
author: {...},
blogPosts: [...]
}
覆盖 keyForRelationship
以格式化此键
// serializers/application.js
export default Serializer.extend({
keyForRelationship(modelName) {
return underscore(modelName);
}
});
现在响应将类似于
{
author: {...},
blog_posts: [...]
}
keyForRelationshipIds(modelName: any): any
使用此钩子来格式化此模型 JSON 表示中 hasMany
关系的 ID 的键。
例如,如果您要序列化一个包含多个 blogPosts
的 author
,默认情况下,您的 author
JSON 会包含一个 blogPostIds
键
{
author: {
id: 1,
blogPostIds: [1, 2, 3]
},
blogPosts: [...]
}
覆盖 keyForRelationshipIds
以格式化此键
// serializers/application.js
export default Serializer.extend({
keyForRelationshipIds(relationship) {
return underscore(relationship) + '_ids';
}
});
现在响应将类似于
{
author: {
id: 1,
blog_post_ids: [1, 2, 3]
},
blogPosts: [...]
}
normalize(json: any): any
此方法由 POST 和 PUT 简写使用。这些简写期望请求中包含有效的 JSON:API 文档,以便它们知道如何创建或更新相应的资源。 normalize 方法允许您将请求主体转换为 JSON:API 文档,这使您能够在原本可能无法使用简写的情况下利用它们。
请注意,如果您已经使用 JSON:API,此方法将不起作用,因为与 POST 和 PUT 请求一起发送的请求有效负载将已经处于正确的格式。
查看包含的 ActiveModelSerializer
的 normalize 方法以获取示例。
serialize(primaryResource: any, request: any): Object
覆盖此方法以实现您自己的自定义序列化函数。 response 是您的路由处理程序返回的任何内容,而 request 是 Pretender 请求对象。
返回一个简单的 JavaScript 对象或数组,Mirage 使用它作为对您的应用程序 XHR 请求的响应数据。
您也可以覆盖此方法,调用 super,并在 Mirage 响应之前操作数据。这是一个添加元数据或用于不适合 Mirage 的其他抽象的任何一次性操作的好地方。
serialize(object, request) {
// This is how to call super, as Mirage borrows [Backbone's implementation of extend](https://backbone.npmjs.net.cn/#Model-extend)
let json = Serializer.prototype.serialize.apply(this, arguments);
// Add metadata, sort parts of the response, etc.
return json;
}