序列化器
序列化器負責格式化您的路由處理程序的回應。
應用程式序列化器將會套用到每個回應。若要進行特定的自訂,請定義每個模型的序列化器。
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 還有一個基本的序列化器類別,您可以使用下面文件中記錄的 hook 自訂它
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: 物件
對綱要實例的引用。
適用於參考已註冊的綱要資訊,例如在序列化器的 include hook 中,以包含資源的所有關聯
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 預期使用 snake case 命名法,您可以這樣寫
// serializers/application.js
export default Serializer.extend({
keyForAttribute(attr) {
return underscore(attr);
}
});
現在的回應會像這樣
{
author: {
first_name: 'Link',
last_name: 'The WoodElf'
}
}
keyForCollection(modelName: any): any
用於自訂序列化主要集合時的鍵。預設情況下,此方法會將 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: any): any
如同 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'
}
}
這個 hook 控制如何序列化 id
欄位(在上述範例中為 commentableId
)。預設情況下,它會將關聯名稱轉換為 camelCase 並加上 Id
作為後綴。
keyForPolymorphicForeignKeyType(relationshipName: String): String
多型關聯會以類型-ID 對表示。
假設有以下模型
Model.extend({
commentable: belongsTo({ polymorphic: true })
});
預設的序列化器會產生
{
comment: {
id: 1,
commentableType: 'post',
commentableId: '1'
}
}
這個 hook 控制如何序列化 type
欄位(在上述範例中為 commentableType
)。預設情況下,它會將關聯名稱轉換為 camelCase 並加上 Type
作為後綴。
keyForRelationship(modelName: any): any
使用此 hook 來格式化與此模型相關的集合的鍵。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
使用此 hook 來格式化此模型 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://backbonejs.dev.org.tw/#Model-extend)
let json = Serializer.prototype.serialize.apply(this, arguments);
// Add metadata, sort parts of the response, etc.
return json;
}