序列化器

序列化器負責格式化您的路由處理程序的回應。

應用程式序列化器將會套用到每個回應。若要進行特定的自訂,請定義每個模型的序列化器。

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'
}

並且您只想要 idtitle,您可以寫入

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-postauthor,並且您想要側載這些,請在 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(預設值),如果該關聯與回應中的模型或集合一起包含(側載),將會序列化關聯的 id
  • always 將始終序列化回應中模型或集合的所有關聯的 id
  • never 將永遠不會序列化回應中模型或集合的關聯 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 關聯。

例如,如果您正在序列化一個會側載一個 authorblogPost,您的 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 是關聯的命名參數。

例如,如果您正在序列化一個會側載多個 blogPostsauthor,預設的回應會看起來像這樣

{
  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 的鍵。

例如,如果您正在序列化一個會側載多個 blogPostsauthor,預設情況下,您的 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;
}