OpenAPIのスキーマファイルを作成する

# 1. はじめに
* OpenAPIのスキーマファイルを作る時の手順を自分なりに整理したい
* バリデーションなど実用的なコンポーネントの作成ルールをまとめたい

# 2. 開発環境
* OpenAPI V.3.0
* Visual Studio Code

# 3. WebAPIサービス設計
## 3.1. HTTP/1.1メソッド、ステータスの定義
|NO  |処理内容  |メソッド  |正常/異常  |ステータス  |ステータス  |備考  |
|---|---|---|---|---|---|---|
|1|・一覧取得|GET|正常|200|Success|ResponseBodyあり|
|---|・詳細取得|---|異常|404|Not Found|---|
|2|作成|POST|正常|201|Created|ResponseBodyなし|
|---|---|---|異常|400|Bad Request|---|
|3|更新|PUT|正常|200|Success|更新時|
|---|---|---|正常|201|Created|作成時|
|---|---|---|異常|404|Not Found|---|
|4|削除|DELTE|正常|204|No Content|---|
|---|---|---|異常|404|Not Found|---|
|5|共通|---|異常|401|Unauthorized|認証エラー|
|---|---|---|異常|500|Unauthorized|サーバーエラー|
|---|---|---|異常|503|Unauthorized|メンテナンス中|

## 3.2. パラメータ種類の定義
|NO  |処理内容  |メソッド  |パラメータ種類  |
|---|---|---|---|
|1|・一覧取得|GET|パスパラメータ or クエリパラメータ|
|---|・詳細取得|---|---|
|2|作成|POST|リクエストボディ|
|3|更新|PUT|リクエストボディ|
|4|削除|DELETE|パスパラメータ or クエリパラメータ|
		
# 4. OpenAPIスキーマ定義
## 4.1. ルートオブジェクト
```yaml:
openapi: "3.0.0"    # 必須
    ...
info:    # 必須
    ...
paths:    # 必須
    ...
servers:
    ...
components:
    ...
security:
    ...
externalDocs:
    ...
```

## 4.2. オブジェクト詳細
### 4.2.1. openapi
* OpenAPIのバージョン情報を定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/6be6a248-1b14-ff5c-b866-86db23376707.png)

### 4.2.2. info
* API定義のメタ情報を定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1d8aecab-de8c-4f95-7a03-0f4cb81132ec.png)

### 4.2.3. servers
* 接続可能なサーバを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/a7ccaa82-31e3-f849-f6f8-8818f0c75e8b.png)

### 4.2.4. paths
* APIのパスを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1e32b7cf-7141-1697-c9aa-858da4e27ab7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/436c524c-58fb-90b7-fb0c-c0bd574c9ce8.png)

### 4.2.5. Components 
* 分類ごとのコンポーネントを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/d670f7da-98d6-bcc2-639a-7540a346e6f1.png)

```yaml:
paths:
  /userId/{userId}:
    get:
      summary: "UserIDの取得"
      description: "UserIDの取得"
      operationId: "GetUserId"
      tags: 
        - userid
      parameters:
        - $ref: '#/components/parameters/userId'
 # （中略）
components:
  parameters:
    userId:
      name: userId
      in: path
      description: "UserId"
      required: true
      schema:
        type: integer
```


### 4.2.6. security
* 利用するセキュリティを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/2b200481-fe9b-945b-5a1f-65e2b4760786.png)

### 4.2.7. tags
* APIを分類するタグを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/40fbb2f1-dc92-c495-6153-257c2b8d6451.png)

### 4.2.8. externalDocs
* 外部ドキュメントを記述する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/d083bb36-15b1-7393-f5c2-753eff069e11.png)

## 4.3. 基本となるデータ型
### 4.3.1. 型
* 主要な型は6種類

| 型 | 説明 |
|---|---|
|integer|整数|
|number|浮動小数|
|string|文字列|
|boolean|真偽値|
|object|オブジェクト|
|array|配列|

### 4.3.2. フォーマット

| 型 | タイプ | 説明 | 
|---|---|---|
|integer|int32|符号付き32ビット整数|
|integer|int64|符号付き64ビット整数|
|number|float|浮動小数|
|number|double|倍精度浮動小数|
|string|なし|文字列|
|string|byte|Base64エンコードされた文字列|
|string|binary|バイナリー|
|string|date|日付の文字列|
|string|date-time|日時の文字列|
|string|email|メールアドレスを示す文字列|
|string|password|パスワードを示す文字列|
|string|hostname|ホスト名を示す文字列|
|string|ipv4|"."（ピリオド）で区切られたIPv4アドレス文字列|
|string|uri|URIフォーマットに従った文字列|
|string|uuid|UUID文字列|


## 4.4. バリデーション
### 4.4.1. 型チェック、必須入力チェック
```yaml:
parameters: 
  - name: id
    in: path
    description: "ID of pet to use"
    required: true  # 必須チェック
    schema:  # 型チェック
      type: integer
      format: int32
```

### 4.4.2. 桁数チェック  
* 文字列 の場合
    * 最大桁数：maxLength
    * 最小桁数：minLength

```yaml:
parameters:
  - name: id
    in: path
    required: true
    description: "ID"
    schema:
       type: string
       minLength: 0
       maxLength: 1
```

* 数値または整数値の場合
    * 最大値（境界値を含む）：minimum
    * 最小値（境界値を含む）：maximum
    * 境界値を含まない場合のみexclusiveMinimum: trueまたはexclusiveMaximum: trueを定義

```yaml:
parameters:
  - name: id
    in: path
    required: true
    description: "ID"
    schema:
      type: integer
      format: int32
      minimum: 1
      exclusiveMaximum: true
      maximum: 100
      # 1 <= ID < 100
```


* 配列の場合
    * 最大要素数：maxItems
    * 最小要素数：minItems
    * ※required: trueの場合は原則としてminItems: 1を定義する
 
```yaml:
parameters:
  - name: ids
    in: query
    description: "タスクIDの配列"
    required: true
    schema:
       type: array
       items:
         type: integer
       minItems: 1
       maxItems: 100
```

### 4.4.3. 区分値チェック 
* 文字列の場合

```yaml:
parameters:
  - name: sort
    in: query
    required: true
    description: "ソート順"
    schema:
      type: string
      enum:
        - asc
        - desc
```

### 4.4.4. 入力可能文字チェック（Pattern）

```yaml:
parameters:
  - name: ssn
    in: query
    required: true
    description: "Social Security Number (SSN)"
    schema:
      type: string
      pattern: '^\d{3}-\d{2}-\d{4}$' # 123-45-6789
```

# 5. 参考文献

https://spec.openapis.org/oas/v3.0.0.html#schema

https://future-architect.github.io/articles/20200409/

https://qiita.com/rllllho/items/53a0023b32f4c0f8eabb

https://qiita.com/KNR109/items/7e094dba6bcf37ed73cf

https://qiita.com/KNR109/items/d3b6aa8803c62238d990

https://qiita.com/shigeru10/items/8f20fafd04f7901da939

https://girigiribauer.com/tech/20190318/

https://qiita.com/tashinoso/items/1437ae404cf129d97f2a

https://qiita.com/halhorn/items/e47673eecc4a01ffb3a0

https://garafu.blogspot.com/2020/05/how-to-use-oas.html