Skip to content
ADP
API Design PrincipleBETA

[ADP-360] 資源擴展

指導原則

  • 預設情況下不應(SHOULD NOT)返回獨立的子資源

    http
    GET /orders/{orderId} HTTP/1.1
    
    {
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "orderedAt": "2024-07-05"
    }

    預期該資源有項目和運送作為獨立的子資源(例如,每個資源都有自己的id)

INFO

為了優化效能,子資源(如項目和運送)應該作為獨立資源進行維護,並擁有自己的識別碼。這種方法能夠實現高效的資源管理和擴展性。

雖然你可以設計一個 API 在單一回應中返回所有相關資源,但這必須在 API 規範中明確說明。本原則提供了一個標準化機制,用於擴展預設回應中未包含的相關資源。

  • 應(SHOULD)支持通過 embed 查詢參數嵌入子資源

    http
    GET /orders/{order-id}?embed=(items)
    
    {
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "items": [
        {
          "orderItemId": "1",
          "productId": "987",
          "productName": "Widget",
          "quantity": 2,
          "price": 25.00
        },
        {
          "orderItemId": "2",
          "productId": "654",
          "productName": "Gadget",
          "quantity": 1,
          "price": 50.00
        }
      ],
      "shipping": {
        "shippingId": "56789",
        "carrier": "UPS",
        "trackingNumber": "1Z9999999999999999",
        "estimatedDeliveryDate": "2024-07-10"
      }
    }
  • 應(SHOULD)使用標準 JSON 結構來嵌入資源,並使用清晰的屬性命名

    http
    GET /orders/{order-id}?embed=(items,shippings)
    
    {
      "id": "uuid-...",
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "items": [
        {
          "orderItemId": "1",
          "productId": "987",
          "productName": "Widget",
          "quantity": 2,
          "price": 25.00,
          "links": {
            "self": "/products/987"
          }
        },
        {
          "orderItemId": "2",
          "productId": "654",
          "productName": "Gadget",
          "quantity": 1,
          "price": 50.00,
          "links": {
            "self": "/products/654"
          }
        }
      ],
      "shipping": {
        "shippingId": "56789",
        "carrier": "UPS",
        "trackingNumber": "1Z9999999999999999",
        "estimatedDeliveryDate": "2024-07-10",
        "links": {
          "self": "/shippings/56789"
        }
      }
    }
  • 應(SHOULD)使用 Link 標頭根據 RFC 8288 進行資源間的導航

    http
    GET /orders/12345?embed=(items,shippings) HTTP/1.1
    
    HTTP/1.1 200 OK
    Content-Type: application/json
    Link: </orders/12345>; rel="self", </orders/12345/items>; rel="items", </orders/12345/shippings>; rel="shippings"
    
    {
      "id": "uuid-...",
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "items": [...],
      "shipping": {...}
    }
  • 應(SHOULD)在 API 規範中記錄可用的嵌入選項

  • 應(SHOULD)限制嵌入資源的深度以防止性能問題

  • 應(SHOULD)實現適當的錯誤處理以應對無效的嵌入請求

OpenAPI 3.1.0 示例

yaml
openapi: 3.1.0
info:
  title: 訂單 API
  version: 1.0.0
paths:
  /orders/{orderId}:
    get:
      summary: 獲取訂單
      parameters:
        - name: embed
          in: query
          description: 嵌入相關資源
          schema:
            type: array
            items:
              type: string
              enum:
                - items
                - shippings
          collectionFormat: csv
      responses:
        '200':
          description: 成功回應
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
components:
  schemas:
    Order:
      type: object
      properties:
        orderId:
          type: string
        customerName:
          type: string
        totalPrice:
          type: number
        orderedAt:
          type: string
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        shipping:
          $ref: '#/components/schemas/Shipping'
    OrderItem:
      type: object
      properties:
        orderItemId:
          type: string
        productId:
          type: string
        productName:
          type: string
        quantity:
          type: integer
        price:
          type: number
    Shipping:
      type: object
      properties:
        shippingId:
          type: string
        carrier:
          type: string
        trackingNumber:
          type: string
        estimatedDeliveryDate:
          type: string

參考

設計參考

更新紀錄

  • 2025-03-07:Add the consideration description.