私の「簡素化された」APIでは、すべての応答は基本の「応答」クラスから派生します(inherit)。応答クラスは、composedメタデータで満たされたヘッダーと、ユーザーが要求しているコアデータを含む本文です。応答(JSON形式)は、すべてのメタデータが最初の「レイヤー」にあり、本文が「本文」という単一の属性であるようにレイアウトされます
response
|--metadata attribute 1 (string/int/object)
|--metadata attribute 2 (string/int/object)
|--body (object)
|--body attribute 1 (string/int/object)
|--body attribute 2 (string/int/object)
次のJSONを使用して、この関係をswaggerで定義しようとしました。
{
...
"definitions": {
"response": {
"allOf": [
{
"$ref": "#/definitions/response_header"
},
{
"properties": {
"body": {
"description": "The body of the response (not metadata)",
"schema": {
"$ref": "#/definitions/response_body"
}
}
}
}
]
},
"response_header": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string",
"description": "value of 'success', for a successful response, or 'error' if there is an error",
"enum": [
"error",
"success"
]
},
"message": {
"type": "string",
"description": "A suitable error message if something went wrong."
}
}
},
"response_body": {
"type": "object"
}
}
}
次に、body/headerを継承するさまざまなbody/headerクラスを作成してさまざまな応答を作成し、関連するheader/bodyクラスで構成される子応答クラスを作成しようとします(下部のソースコードを参照)。ただし、これが物事を行うための間違った方法であるか、私の実装が間違っているかのどちらかです。 swagger 2.0 specification (以下に示す)で継承の例を見つけることができませんでしたが、 composition の例を見つけました。
この「差別者」が果たすべき役割は大きいと確信していますが、何をする必要があるのかはわかりません。
以下のサンプルコードを「修正」することにより、誰かがSwagger 2.0(JSON)で合成+継承を実装する方法を教えてください。また、ヘッダーの「結果」属性が常に「エラー」に設定されている応答から継承するErrorResponseクラスを指定できると便利です。
{
"swagger": "2.0",
"info": {
"title": "Test API",
"description": "Request data from the system.",
"version": "1.0.0"
},
"Host": "xxx.xxx.com",
"schemes": [
"https"
],
"basePath": "/",
"produces": [
"application/json"
],
"paths": {
"/request_filename": {
"post": {
"summary": "Request Filename",
"description": "Generates an appropriate filename for a given data request.",
"responses": {
"200": {
"description": "A JSON response with the generated filename",
"schema": {
"$ref": "#/definitions/filename_response"
}
}
}
}
}
},
"definitions": {
"response": {
"allOf": [
{
"$ref": "#/definitions/response_header"
},
{
"properties": {
"body": {
"description": "The body of the response (not metadata)",
"schema": {
"$ref": "#/definitions/response_body"
}
}
}
}
]
},
"response_header": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "string",
"description": "value of 'success', for a successful response, or 'error' if there is an error",
"enum": [
"error",
"success"
]
},
"message": {
"type": "string",
"description": "A suitable error message if something went wrong."
}
}
},
"response_body": {
"type": "object"
},
"filename_response": {
"extends": "response",
"allOf": [
{
"$ref": "#definitions/response_header"
},
{
"properties": {
"body": {
"schema": {
"$ref": "#definitions/filename_response_body"
}
}
}
}
]
},
"filename_response_body": {
"extends": "#/definitions/response_body",
"properties": {
"filename": {
"type": "string",
"description": "The automatically generated filename"
}
}
}
}
}
私が望むものを明確にするために、以下の非常に基本的な図を作成しました。これは、すべての応答がresponse_headerとresponse_bodyオブジェクトの任意の組み合わせを使用して構築された「応答」オブジェクトのインスタンス化であることを示すことを目的としています。 response_headerおよびresponse_bodyオブジェクトを拡張して、任意の応答オブジェクトに挿入できます。これは、ベースresponse_bodyクラスの子filename_response_bodyを使用するfilename_responseの場合に実行されます。エラーと成功の両方の応答は、「応答」オブジェクトを使用します。
Swaggerの初心者として、私は 公式ドキュメント ポリモーフィズムと構成について理解しやすいとは思いません。なぜなら、には例がないからです。ネットを検索したとき、多くの 良い例extends
が有効であるときにswagger 1.2を参照していました。
swagger 2.0の場合、 githubのswagger spec sources を介して google group で良い例を見つけました
上記のソースに基づいて、YAMLでの短い有効な継承の例を次に示します。
definitions:
Pet:
discriminator: petType
required:
- name
- petType # required for inheritance to work
properties:
name:
type: string
petType:
type: string
Cat:
allOf:
- $ref: '#/definitions/Pet' # Cat has all properties of a Pet
- properties: # extra properties only for cats
huntingSkill:
type: string
default: lazy
enum:
- lazy
- aggressive
Dog:
allOf:
- $ref: '#/definitions/Pet' # Dog has all properties of a Pet
- properties: # extra properties only for dogs
packSize:
description: The size of the pack the dog is from
type: integer
discriminator
を定義しなくても構図がうまく機能することがわかりました。
たとえば、ベースResponse
:
definitions:
Response:
description: Default API response
properties:
status:
description: Response status `success` or `error`
type: string
enum: ["success", "error"]
error_details:
description: Exception message if called
type: ["string", "object", "null"]
error_message:
description: Human readable error message
type: ["string", "null"]
result:
description: Result body
type: ["object", "null"]
timestamp:
description: UTC timestamp in ISO 8601 format
type: string
required:
- status
- timestamp
- error_details
- error_message
- result
次のようにレンダリングされます。
そして、それを拡張してresult
フィールドのカスタムスキーマを改良できます。
FooServiceResponse:
description: Response for Foo service
allOf:
- $ref: '#/definitions/Response'
- properties:
result:
type: object
properties:
foo_field:
type: integer
format: int32
bar_field:
type: string
required:
- result
そして、それは次のように正しくレンダリングされます:
これが機能するにはallOf
で十分であり、discriminator
フィールドは使用されないことに注意してください。これは機能するため、これは重要です。これは、ツールがdiscriminator
フィールドなしでコードを生成できるようになるためです。
ここでのすべての答えはすでに優れていますが、 composition vs inheritance に関するちょっとしたメモを追加したいだけです。 Swagger/OpenAPI Spec によると、compositionを実装するには、allOf
プロパティを使用するだけで十分です- @ oblalexが正しく指摘している 。ただし、inheritanceを実装するには、 @の例のように、allOf
とともにdiscriminator
を使用する必要があります。 TomaszSętkowski 。
また、API Handymanで composition と inheritance の両方のSwaggerの例をいくつか見つけました。これらはArnaud Lauretによる excellent Swagger/OpenAPIチュートリアルシリーズ の一部であり、誰もがチェックすべきだと思います。
共有したSwagger 2.0の標準例は、構成関係を示しています。具体的には、「一種」のスーパータイプ/サブタイプの関係をキャプチャしますが、それ自体はポリモーフィズムではありません。
入力パラメーターとしてPetの基本定義を参照し、Catを選択するか、入力要求の値としてCat JSONオブジェクトを入力し、これをSwagger UIで受け入れられるようにすることができます。
これを直接動作させることはできませんでした。
基本的なオブジェクト(Petなど)でadditionalPropertiesをtrueに設定し、JSONポインター参照を入力スキーマとして使用してPetを指定し、最後にCat JSON値オブジェクトをSwagger UIにコピーして貼り付けることができました。追加のプロパティが許可されているため、Swagger UIは有効な入力要求ペイロードを生成しました。