Open15

Swagger(OAS3.0)チュートリアルの和訳

marbullmarbull

OpenAPIの最新バージョンは3.0です。OpenAPIの定義は、JSONまたはYAMLで記述することができます。YAMLの方が読みやすく、書きやすいので、YAMLをお勧めします。

marbullmarbull

単純なOpenAPI 3.0の仕様は次のようになります。

openapi: 3.0.0
info:
  version: 1.0.0
  title: Sample API
  description: A sample API to illustrate OpenAPI concepts
paths:
  /list:
    get:
      description: Returns a list of stuff              
      responses:
        '200':
          description: Successful response
marbullmarbull

APIを作成する

あるレコード会社のAPIを設計することとします。そして,以下の情報を持つアーティストのデータベースを持っていると仮定します。

  • Artist name
  • Artist genre
  • Number of albums published under the label
  • Artist username

このAPIにより、ユーザはデータベースに保存されているアーティストのリストを取得し、新しいアーティストをデータベースに追加することができるようになります。

OpenAPI仕様で定義されたAPIは、大きく3つのセクションに分けることができます。

  • Meta information(メタ情報)
  • Path items (endpoints):(パス項目(エンドポイント))
    • Parameters(パラメータ)
    • Request bodies(リクエストボディ)
    • Responses(レスポンス)
  • Reusable components:(再利用可能なコンポーネント)
    • Schemas (data models)(スキーマ(データモデル))
    • Parameters(パラメータ)
    • Responses(レスポンス)
    • Other components(その他のコンポーネント)
marbullmarbull

Meta information(メタ情報)

まずは、APIのタイトルやバージョン、サーバーのURLなど、説明的なメタ情報のみを含むシンプルなAPI定義から始ます

openapi: 3.0.0
info:
  version: 1.0.0
  title: Simple Artist API
  description: A simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

# Basic authentication
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
security:
  - BasicAuth: []

paths: {}

各API定義は、この定義が使用するOpenAPI仕様のバージョンから始まります。info オブジェクトには、API のタイトルとバージョン (必須)、そしてオプションで説明を指定します。

servers 配列は、API 呼び出し用のサーバの URL を複数指定します。API のエンドポイントのパスは、サーバ URL の後に追加されます。API の中には単一のサーバを持つものもあれば、 プロダクションサーバとサンドボックスサーバのように複数のサーバを持つものもあります。この例では、サーバーのURLはhttps://example.io/v1。

また、APIはBasic認証で保護されており、認証されたユーザーのみがAPIを利用することができます。

marbullmarbull

Path items(パス項目)

パス項目はAPIのエンドポイントであり、その下にリソースを目的の方法で操作するためのHTTPメソッドを指定することができます。これらのエンドポイントは、サーバーの URL からの相対パスで、この例では https://example.io/v1 になっています。

ここでは、/artistsというエンドポイントと、このエンドポイントに対するGETメソッドを定義します。したがって、クライアントはアーティストのリストを取得するためにGET https://example.io/v1/artists を使用することになります。

#  ----- Added lines  ----------------------------------------
paths:
  /artists:
    get:
     description: Returns a list of artists 
#  ---- /Added lines  ----------------------------------------
marbullmarbull

Responses(レスポンス)

GET メソッドは artists エンドポイントで、API の消費者は https://example.io/v1 データベースからアーティスト一覧の詳細を取得することができます。

すべてのレスポンスには、少なくとも1つのHTTPステータスコードが必要で、消費者が期待するレスポンスの種類を記述します。この記述によって、APIのレスポンスがどのようなものであるかの詳細が示される。このサンプルコードでは、200を指定していますが、これはクライアントのリクエストが成功した場合であり、400はリクエストが失敗した場合です。成功した場合は、アーティスト名、ジャンル、ユーザー名、記録されたアルバムが返されます。リクエストに失敗した場合は、400のHTTPコードで説明され、対応するエラーメッセージでなぜそのレスポンスが無効であるかが詳しく説明されます。

paths:
  /artists:
    get:
      description: Returns a list of artists 
      #  ----- Added lines  ----------------------------------------
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  required:
                    - username
                  properties:
                    artist_name:
                      type: string
                    artist_genre:
                      type: string
                    albums_recorded:
                      type: integer
                    username:
                      type: string

        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string
      #  ---- /Added lines  ----------------------------------------
marbullmarbull

Parameters(パラメータ)

RESTful パラメータは、ユーザーが操作するリソースの変数部分を指定します。

Query parameters(クエリパラメータ)

クエリーパラメーターは、最も一般的なタイプのパラメーターです。クエリパラメータは、URLの末尾のクエスチョンマークに続いて表示されます。クエリパラメータは任意であり、一意ではないので、URL内で複数回指定することができます。これは、URLの非階層的な構成要素です。

この例では、データベースからアーティストの全リストを返す代わりに、クライアントが必要な情報を制限できるようにすることが理にかなっており、それはサーバーに不必要な負荷をかけることにつながります。例えば、クライアントはページ番号(オフセット)とページ上の情報量(制限)を記述することができます。

GET https://example.io/v1/artists?limit=20&offset=3

これらの変数は、OpenAPI定義のparametersオブジェクトの下に定義されています。したがって、この仕様は次のようになります。

get:
      description: Returns a list of artists 
      #  ----- Added lines  ----------------------------------------
      parameters:
        - name: limit
          in: query
          description: Limits the number of items on a page
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the page number of the artists to be displayed
          schema:
            type: integer
      #  ---- /Added lines  ----------------------------------------         
      
      responses:
        '200':
marbullmarbull

Request body(リクエストボディ)

POST、PUT、PATCHリクエストは通常、リクエストボディを含んでいます。リクエストボディは、requestBodyオブジェクトを使用して定義します。このAPIでは、ユーザがアーティストをデータベースに投稿する機能を追加してみましょう。これは、/artists リソースの下になります。

このAPIは、次のようになります。

paths:
  /artists:
    get:
      description: Returns a list of artists 
      parameters:
        - name: limit
          in: query
          description: Limits the number of items on a page
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the page number of the artists to be displayed
          schema:
            type: integer
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  required:
                    - username
                  properties:
                    artist_name:
                      type: string
                    artist_genre:
                      type: string
                    albums_recorded:
                      type: integer
                    username:
                      type: string
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string

    #  ----- Added lines  ----------------------------------------
    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object 
              required:
                - username
              properties:
                artist_name:
                  type: string
                artist_genre:
                  type: string
                albums_recorded:
                  type: integer
                username:
                  type: string

      responses:
        '200':
          description: Successfully created a new artist

        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string
    #  ---- /Added lines  ----------------------------------------
marbullmarbull

Path parameters(パスパラメータ)

パスパラメータは、例えば https://example.io/v1/artists/{username} のように、クライアントが扱うデータの特定のコンポーネントを分離するために使用することができます。パスパラメータは、URLの階層的なコンポーネントの一部であるため、順次積み重ねられます。

提供されたユーザ名に基づいて特定のアーティストの情報を返す新しいエンドポイントを作成してみましょう。ここでのパス・パラメータは、情報を必要とするアーティストのユーザ名となります。パス・パラメータ(この場合はユーザー名)は、メソッドの下の parameters オブジェクトに必ず記述しなければなりません。

post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object 
              required:
                - username
              properties:
                artist_name:
                  type: string
                artist_genre:
                  type: string
                albums_recorded:
                  type: integer
                username:
                  type: string
      responses:
        '200':
          description: Successfully created a new artist
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string

  #  ----- Added lines  ----------------------------------------
  /artists/{username}:
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
          
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
                
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object 
                properties:           
                  message:
                    type: string
  #  ---- /Added lines  ----------------------------------------

ここでは、ユーザー名をpathパラメータとして指定しています。注意点としては、pathパラメータは、requiredパラメータにtrueプロパティが設定されていないと、仕様が有効にならないことです。

ここまで辿り着いたら、おめでとうございます。レコード会社のためのシンプルなAPIを設計できましたね。

marbullmarbull

Reusable components(再利用可能なコンポーネント)

今説明したのは、2つのエンドポイントと3つのアクションだけです。これは約130行の仕様で、APIが大きくなればなるほど、仕様は長くなる一方です。これまでの仕様でお気づきの点は、同じArtistスキーマ(アーティスト名、ジャンル、ユーザー名、公開アルバム)が様々な200や400レスポンスで繰り返されていることでしょう。大きなAPIになると、同じ仕様の多くを書き換えて再利用することになるので、より複雑なAPIを書くのは退屈な作業になるでしょう。

OpenAPI仕様には解決策がます。それは同じAPIで複数のエンドポイントにまたがって使える再利用可能なコンポーネントです。これらのコンポーネントはグローバルコンポーネントセクションで定義され、個々のエンドポイントから参照される。仕様書では、様々なタイプの再利用可能なコンポーネントを定義しています。

  • Schemas (data models)
  • Parameters
  • Request bodies
  • Responses
  • Response headers
  • Examples
  • Links
  • Callbacks
marbullmarbull

Schemas(スキーマ)

グローバルコンポーネントセクションのスキーマサブセクションには、APIによって消費され返される様々なデータモデルを格納することができます。ここでは、HTTP 200 OK レスポンスのスキーマを格納するためにコンポーネントを使用する方法を説明します。API の定義には、すでに securitySchemes を含む components セクションがありましたが、components を一番下に移動し、schemas サブセクションを追加しています。

openapi: 3.0.0
info:
  version: 1.0.0
  title: Simple API
  description: A simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

security:
  - BasicAuth: []

paths:
  /artists:
    get:
      description: Returns a list of artists 
      parameters:
        - name: limit
          in: query
          description: Limits the number of items on a page
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the page number of the artists to be displayed
          schema:
            type: integer
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  #  ----- Added line  ----------------------------------------
                  $ref: '#/components/schemas/Artist'
                  #  ---- /Added line  ----------------------------------------
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string

    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              #  ----- Added line  ----------------------------------------
              $ref: '#/components/schemas/Artist'
              #  ---- /Added line  ----------------------------------------
      responses:
        '200':
          description: Successfully created a new artist
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:   
                  message:
                    type: string

  /artists/{username}:
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
          
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
                
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object 
                properties:           
                  message:
                    type: string

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic

  #  ----- Added lines  ----------------------------------------                
  schemas:
    Artist:
      type: object
      required:
        - username
      properties:
        artist_name:
          type: string
        artist_genre:
            type: string
        albums_recorded:
            type: integer
        username:
            type: string
  #  ---- /Added lines  ----------------------------------------

仕様が短くなるだけでなく、同じスキーマを持つ新しいエンドポイントが必要になったときにいつでも、設計者はその部分を書くのに時間を費やす必要がありません。
marbullmarbull

Parameters and Responses(パラメータとレスポンス)

コンポーネントセクションには、再利用可能なパラメータとレスポンスを格納するためのサブセクションもあります。以下の仕様では、再利用可能なクエリパラメータ offset と limit を定義し、/artists エンドポイントでそれらを参照しています。また、再利用可能な400Errorレスポンスも定義し、すべてのエンドポイントから参照するようにしています。

openapi: 3.0.0
info:
  version: 1.0.0
  title: Simple API
  description: A simple API to illustrate OpenAPI concepts

servers:
  - url: https://example.io/v1

security:
  - BasicAuth: []

paths:
  /artists:
    get:
      description: Returns a list of artists 
      parameters:
        #  ----- Added line  ------------------------------------------
        - $ref: '#/components/parameters/PageLimit'
        - $ref: '#/components/parameters/PageOffset'
        #  ---- /Added line  ------------------------------------------
      responses:
        '200':
          description: Successfully returned a list of artists
          content:
            application/json:
              schema:
                type: array
                items:
                  #  ----- Added line  --------------------------------
                  $ref: '#/components/schemas/Artist'
                  #  ---- /Added line  --------------------------------
        '400':
          #  ----- Added line  ----------------------------------------
          $ref: '#/components/responses/400Error'
          #  ---- /Added line  ----------------------------------------

    post:
      description: Lets a user post a new artist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              #  ----- Added line  ------------------------------------
              $ref: '#/components/schemas/Artist'
              #  ---- /Added line  ------------------------------------
      responses:
        '200':
          description: Successfully created a new artist
        '400':
          #  ----- Added line  ----------------------------------------
          $ref: '#/components/responses/400Error'
          #  ---- /Added line  ----------------------------------------    

  /artists/{username}:
    get:
      description: Obtain information about an artist from his or her unique username
      parameters:
        - name: username
          in: path
          required: true
          schema:
            type: string
          
      responses:
        '200':
          description: Successfully returned an artist
          content:
            application/json:
              schema:
                type: object
                properties:
                  artist_name:
                    type: string
                  artist_genre:
                    type: string
                  albums_recorded:
                    type: integer
                
        '400':
          #  ----- Added line  ----------------------------------------
          $ref: '#/components/responses/400Error'
          #  ---- /Added line  ----------------------------------------     

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic

  schemas:
    Artist:
      type: object
      required:
        - username
      properties:
        artist_name:
          type: string
        artist_genre:
            type: string
        albums_recorded:
            type: integer
        username:
            type: string

  #  ----- Added lines  ----------------------------------------
  parameters:
    PageLimit:
      name: limit
      in: query
      description: Limits the number of items on a page
      schema:
        type: integer
      
    PageOffset:
      name: offset
      in: query
      description: Specifies the page number of the artists to be displayed
      schema:
        type: integer

  responses:
    400Error:
      description: Invalid request
      content:
        application/json:
          schema:
            type: object 
            properties:
              message:
                type: string
  #  ---- /Added lines  ----------------------------------------

定義にジャンプするには、$ref リンクをクリックするだけです。

marbullmarbull

まとめ

レコード会社のデータベースに存在するアーティストを公開するRESTfulなAPIを設計することに成功しました! OpenAPIの基本的な部分のみを説明しましたが、この仕様は、あなたが望むものであれば(ほとんど)何でも可能です。OpenAPIのエキスパートになりたい方は、OpenAPI 3.0仕様書やハウツーガイドを参照するか、認定コースを試してみてください。

仕様書:https://swagger.io/specification/
ハウツーガイド:https://swagger.io/docs/specification/basic-structure/
認定コース:https://smartbear.com/academy/