次の方法で共有


ASP.NET Core アプリに OpenAPI メタデータを含める

この記事では、ASP.NET Core アプリに OpenAPI メタデータを追加する方法について説明します。

エンドポイントの OpenAPI メタデータを含める

ASP.NET は、Web アプリのエンドポイントからメタデータを収集し、それを使用して OpenAPI ドキュメントを生成します。

コントローラー ベースのアプリでは、コントローラーに[EndpointDescription]属性があるときに、[HttpPost][Produces][ApiController]などの属性からメタデータが収集されます。

最小限の API では、メタデータは属性から収集できますが、ルート ハンドラーから TypedResults を返すなどの拡張メソッドやその他の戦略を使用して設定することもできます。

次の表に、収集されるメタデータと、それを設定するための戦略の概要を示します。

メタデータ 属性 拡張メソッド その他の戦略
まとめ [EndpointSummary] WithSummary
説明 [EndpointDescription] WithDescription
タグ [Tags] WithTags
operationId [EndpointName] WithName
パラメーター [FromQuery][FromRoute][FromHeader][FromForm]
パラメーターの説明 [Description]
リクエストボディ [FromBody] Accepts
応答 [Produces] ProducesProducesProblem TypedResults
エンドポイントの除外 [ExcludeFromDescription][ApiExplorerSettings] ExcludeFromDescription

ASP.NET Core では、XML ドキュメントのコメントからメタデータを収集することもできます。 詳細については、 ASP.NET Core ASP.NET Core OpenAPI XML ドキュメントコメントのサポート に関するページを参照してください。

次のセクションでは、生成された OpenAPI ドキュメントをカスタマイズするためにアプリにメタデータを含める方法を示します。

要約と説明

エンドポイントの概要と説明は、[EndpointSummary] 属性と [EndpointDescription] 属性を使用して、または Minimal API で、WithSummaryWithDescription 拡張メソッドを使用して設定できます。

次のサンプルでは、概要と説明を設定するためのさまざまな方法を示します。

属性は app.MapGet メソッドではなくデリゲート メソッドに配置されることに注意してください。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithSummary("This is a summary.")
    .WithDescription("This is a description.");

app.MapGet("/attributes",
    [EndpointSummary("This is a summary.")]
    [EndpointDescription("This is a description.")]
    () => "Hello world!");

タグ

OpenAPI では、分類の形式として各エンドポイントでタグを指定することをサポートしています。

Minimal API では、[Tags] 属性または WithTags 拡張メソッドを使用してタグを設定できます。

次のサンプルでは、タグを設定するためのさまざまな戦略を示します。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithTags("todos", "projects");

app.MapGet("/attributes",
    [Tags("todos", "projects")]
    () => "Hello world!");

operationId

OpenAPI では、操作の一意の識別子または名前として、各エンドポイントの operationId がサポートされています。

Minimal API では、[EndpointName] 属性または WithName 拡張メソッドを使用して operationId を設定できます。

次のサンプルでは、operationIdを設定するためのさまざまな戦略を説明します。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithName("FromExtensionMethods");

app.MapGet("/attributes",
    [EndpointName("FromAttributes")]
    () => "Hello world!");

パラメーター

OpenAPI では、API によって使用されるパス、クエリ文字列、ヘッダー、cookie パラメーターの注釈付けをサポートします。

フレームワークは、ルート ハンドラーのシグネチャに基づいて、要求パラメーターの型を自動的に推論します。

[Description] 属性を使用して、パラメーターの説明を指定できます。

[Description]属性は MVC アプリでは機能しますが、現時点では最小限の API アプリでは機能しません。 詳細については、「DescriptionのパラメーターProducesResponseTypeAttribute最小限の API アプリでは機能しません (dotnet/aspnetcore #60518)」を参照してください。

リクエストの本文を説明する

OpenAPI の requestBody フィールドには、サポートされているコンテンツ タイプや本文コンテンツのスキーマなど、API クライアントがサーバーに送信できる要求の本文が記述されています。

エンドポイント ハンドラー メソッドが要求本文からバインドされたパラメーターを受け入れると、ASP.NET Core は OpenAPI ドキュメント内の操作に対応する requestBody を生成します。 要求本文のメタデータは、属性または拡張メソッドを使用して指定することもできます。 追加のメタデータは、 document トランスフォーマー または 操作トランスフォーマーで設定できます。

エンドポイントが要求本文にバインドされたパラメーターを定義せず、代わりに HttpContext から直接要求本文を使用する場合、ASP.NET Core は要求本文メタデータを指定するメカニズムを提供します。 これは、要求本文をストリームとして処理するエンドポイントの一般的なシナリオです。

一部の要求本文メタデータは、ルート ハンドラー メソッドの FromBody または FromForm パラメーターから決定できます。

要求本文の説明は、パラメーターの [Description] 属性を使用して、 FromBody または FromFormで設定できます。

FromBody パラメーターが null 非許容で、EmptyBodyBehaviorAllow 属性のFromBodyに設定されていない場合は、要求本文が必要であり、requiredrequestBody フィールドは、生成された OpenAPI ドキュメントでtrueに設定されます。 フォーム本体は常に必須であり、 requiredtrueに設定します。

document トランスフォーマーまたは操作トランスフォーマーを使用してexampleexamples、またはencodingフィールドを設定したり、生成された OpenAPI ドキュメントの要求本文の仕様拡張を追加したりできます。

要求本文のメタデータを設定するためのその他のメカニズムは、開発するアプリの種類によって異なります。以降のセクションで説明します。

生成された OpenAPI ドキュメント内の要求本文のコンテンツ タイプは、要求本文にバインドされているパラメーターの型、または Accepts 拡張メソッドで指定されたパラメーターの型から決定されます。 既定では、 FromBody パラメーターのコンテンツ タイプは application/json され、 FromForm パラメーターのコンテンツ タイプは multipart/form-data または application/x-www-form-urlencodedされます。

これらの既定のコンテンツ タイプのサポートは最小限の API に組み込まれており、その他のコンテンツ タイプはカスタム バインドを使用して処理できます。 詳細については、最小限の API ドキュメントの Custom バインド トピックを参照してください。

要求本文に異なるコンテンツ タイプを指定するには、いくつかの方法があります。 FromBody パラメーターの型がIEndpointParameterMetadataProviderを実装する場合、ASP.NET Core はこのインターフェイスを使用して、要求本文のコンテンツ タイプを決定します。 フレームワークでは、このインターフェイスの PopulateMetadata メソッドを使用して、要求本文の本文コンテンツのコンテンツ タイプと型を設定します。 たとえば、Todo または application/xml コンテンツ タイプのいずれかを受け入れるtext/xml クラスは、IEndpointParameterMetadataProviderを使用してフレームワークにこの情報を提供できます。

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(
        ParameterInfo parameter,
        EndpointBuilder builder)
    {
        builder.Metadata.Add(
            new AcceptsMetadata(
                ["application/xml", "text/xml"], 
                typeof(Todo)
            )
        );
    }
}

Accepts拡張メソッドを使用して、要求本文のコンテンツ タイプを指定することもできます。 次の例では、エンドポイントは要求本文で Todo オブジェクトを受け入れ、想定されるコンテンツ タイプは application/xml となります。

app.MapPut("/todos/{id}", (int id, Todo todo) => ...)
    .Accepts<Todo>("application/xml");

application/xmlは組み込みのコンテンツ タイプではないため、Todo クラスはIBindableFromHttpContext<TSelf> インターフェイスを実装して、要求本文のカスタム バインドを提供する必要があります。 次に例を示します。

public class Todo : IBindableFromHttpContext<Todo>
{
    public static async ValueTask<Todo?> BindAsync(
        HttpContext context, 
        ParameterInfo parameter)
    {
        var xmlDoc = await XDocument.LoadAsync(context.Request.Body, LoadOptions.None, context.RequestAborted);
        var serializer = new XmlSerializer(typeof(Todo));
        return (Todo?)serializer.Deserialize(xmlDoc.CreateReader());
    }
}

エンドポイントで要求本文にバインドされているパラメーターが定義されていない場合は、 Accepts 拡張メソッドを使用して、エンドポイントが受け入れるコンテンツ タイプを指定します。

AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A<>を複数回指定した場合、最後のメタデータのみが使用されます。これらは結合されません。

応答の種類の説明

OpenAPI では、API から返される応答の記述を提供できます。 ASP.NET Core には、エンドポイントの応答メタデータを設定するためのいくつかの戦略が用意されています。 設定できる応答メタデータには、状態コード、応答本文の種類、応答のコンテンツ タイプが含まれます。 OpenAPI の応答には、説明、ヘッダー、リンク、例などの追加のメタデータが含まれる場合があります。 この追加のメタデータは、 document トランスフォーマー または 操作トランスフォーマーで設定できます。

応答メタデータを設定するための具体的なメカニズムは、開発するアプリの種類によって異なります。

最小 API アプリでは、ASP.NET Core では、エンドポイントの拡張メソッドによって追加された応答メタデータ、ルート ハンドラーの属性、およびルート ハンドラーの戻り値の型を抽出できます。

  • Produces拡張メソッドをエンドポイントで使用して、状態コード、応答本文の種類、エンドポイントからの応答のコンテンツ タイプを指定できます。
  • [ProducesResponseType]またはProducesResponseTypeAttribute<T>属性を使用して、応答本文の型を指定できます。
  • ルート ハンドラーを使用して、応答本文の型とコンテンツ タイプを指定する IEndpointMetadataProvider を実装する型を返すことができます。
  • エンドポイントの ProducesProblem 拡張メソッドを使用して、エラー応答の状態コードとコンテンツ タイプを指定できます。

ProducesおよびProducesProblem拡張メソッドは、RouteHandlerBuilderRouteGroupBuilderの両方でサポートされることに注意してください。 これにより、たとえば、グループ内のすべての操作に対して一般的な一連のエラー応答を定義できます。

上記のいずれかの方法で指定されていない場合、次のようになります。

  • 応答の状態コードの既定値は 200 です。
  • 応答本文のスキーマは、エンドポイント メソッドの暗黙的または明示的な戻り値の型 (たとえば、TTask<TResult>から) から推論できます。それ以外の場合は、指定されていないと見なされます。
  • 指定または推論された応答本文のコンテンツタイプは "application/json" です。

Minimal API では、 Produces 拡張メソッドと [ProducesResponseType] 属性によってエンドポイントの応答メタデータのみが設定されます。 エンドポイントの動作は変更または制約されません。エンドポイントの動作は、メタデータで指定された状態コードまたは応答本文の種類とは異なる場合があり、コンテンツ タイプは、属性または拡張メソッドで指定されたコンテンツ タイプに関係なく、ルート ハンドラー メソッドの戻り値の型によって決定されます。

Produces拡張メソッドでは、エンドポイントの応答の種類を指定できます。既定の状態コードは 200 で、既定のコンテンツ タイプは application/json。 次に例を示します。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

[ProducesResponseType]を使用して、応答メタデータをエンドポイントに追加できます。 次の例に示すように、ルートを作成するためのメソッド呼び出しではなく、ルート ハンドラー メソッドに属性が適用されることに注意してください。

app.MapGet("/todos",
    [ProducesResponseType<List<Todo>>(200)]
    async (TodoDb db) => await db.Todos.ToListAsync());

[ProducesResponseType][Produces]、および [ProducesDefaultResponseType] では、応答を記述するために使用できる Description と呼ばれる省略可能な文字列プロパティもサポートされています。 これは、クライアントが特定の応答を期待できる理由またはタイミングを説明するのに役立ちます。

app.MapGet("/todos/{id}",
    [ProducesResponseType<Todo>(200, 
        Description = "Returns the requested Todo item.")]
    [ProducesResponseType(404, Description = "Requested item not found.")]
    [ProducesDefault(Description = "Undocumented status code.")]
    async (int id, TodoDb db) => /* Code here */);

エンドポイントのルート ハンドラーの実装で TypedResults を使用すると、エンドポイントに対する応答の型のメタデータが自動的に含まれます。 たとえば、以下のコードは、200 コンテンツ タイプでの application/json 状態コードの応答で、エンドポイントに自動的に注釈を付けます。

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync();
    return TypedResults.Ok(todos);
});

IEndpointMetadataProviderを実装した型のみがOpenAPIドキュメント内にresponsesエントリを作成します。 TypedResults エントリを生成するresponses ヘルパー メソッドの一部の一覧を次に示します。

TypedResults 補助的なメソッド 状態コード
Ok() 200
作成済み() 201
CreatedAtRoute() 201
承認済み 2:02
AcceptedAtRoute() 2:02
コンテンツなし() 204
BadRequest() 400
ValidationProblem() 400
NotFound(見つかりません) 404
衝突() 409
UnprocessableEntity(処理できないエンティティ) 422

NoContentを除くすべてのメソッドには、応答本文の型を指定するジェネリック オーバーロードがあります。

エンドポイント メタデータを設定し、ルート ハンドラーから返すクラスを実装できます。

ProblemDetails の応答を設定する

ProblemDetails 応答を返す可能性があるエンドポイントの応答の種類を設定する場合は、次を使用してエンドポイントに適切な応答メタデータを追加できます。

ProblemDetails 応答を返すように最小限の API アプリを構成する方法の詳細については、「最小限の API でエラーを処理する を参照してください

複数応答の種類

エンドポイントがさまざまなシナリオでさまざまな種類の応答を返すことができる場合は、次の方法でメタデータを指定できます。

  • 次の例に示すように、Produces 拡張メソッドを複数回呼び出します。

    app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
             await db.Todos.FindAsync(id) 
             is Todo todo
             ? Results.Ok(todo) 
             : Results.NotFound())
       .Produces<Todo>(StatusCodes.Status200OK)
       .Produces(StatusCodes.Status404NotFound);
    
  • 次の例に示すように、シグネチャで Results<TResult1,TResult2,TResult3,TResult4,TResult5,TResult6> を、ハンドラーの本体で TypedResults を使用します。

    app.MapGet("/book/{id}", Results<Ok<Book>, NotFound> 
        (int id, List<Book> bookList) =>
        {
            return bookList.FirstOrDefault((i) => i.Id == id) is Book book
            ? TypedResults.Ok(book)
            : TypedResults.NotFound();
        });
    

    Results<TResult1,TResult2,TResultN> 共用体型は、ルート ハンドラーが IResult を実装する複数の具象型を返し、IEndpointMetadataProvider を実装するそれらの型はいずれもエンドポイントのメタデータに寄与することを宣言します。

    共用体型は、暗黙的なキャスト演算子を実装します。 これらの演算子により、コンパイラはジェネリック引数で指定されている型を共用体型のインスタンスに自動的に変換できるようになります。 この機能にはさらに、ルート ハンドラーからそうすることが宣言されている結果のみが返されることがコンパイル時にチェックされるという利点があります。 ジェネリック引数の 1 つとして宣言されていない型を Results<TResult1,TResult2,TResultN> に返そうとすると、コンパイル エラーが発生します。

生成されたドキュメントからエンドポイントを除外する

既定では、アプリで定義されているすべてのエンドポイントは生成された OpenAPI ファイルに文書化されますが、エンドポイントは属性または拡張メソッドを使用してドキュメントから除外できます。

除外する必要があるエンドポイントを指定するメカニズムは、開発するアプリの種類によって異なります。

最小限の API では、OpenAPI ドキュメントから特定のエンドポイントを除外するための 2 つの戦略がサポートされています。

次のサンプルでは、生成された OpenAPI ドキュメントから指定されたエンドポイントを除外するためのさまざまな方法を示します。

app.MapGet("/extension-method", () => "Hello world!")
    .ExcludeFromDescription();

app.MapGet("/attributes",
    [ExcludeFromDescription]
    () => "Hello world!");

データ型の OpenAPI メタデータを含める

要求または応答本文で使用される C# クラスまたはレコードは、生成された OpenAPI ドキュメントのスキーマとして表されます。 既定では、スキーマではパブリック プロパティのみが表されますが、フィールドのスキーマ プロパティも作成する JsonSerializerOptions があります。

PropertyNamingPolicy がキャメルケースに設定されている場合 (これは ASP.NET Web アプリケーションの既定値です)、スキーマ内のプロパティ名は、クラスまたはレコードプロパティ名のキャメルケース形式です。 [JsonPropertyName] は、個々のプロパティでスキーマ内のプロパティの名前を指定するために使用できます。

種類と形式

数値型

JSON スキーマ ライブラリは、標準の C# 数値型を、アプリで使用されるtypeformatプロパティに基づき、OpenAPI NumberHandlingおよびJsonSerializerOptionsにマッピングします。 ASP.NET Core Web API アプリでは、このプロパティの既定値は JsonNumberHandling.AllowReadingFromString

NumberHandling プロパティが JsonNumberHandling.AllowReadingFromString に設定されている場合、数値型は次のようにマップされます。

C# 型 OpenAPI type OpenAPI format その他のアサーション
整数 (int) [整数, 文字列] int32 パターン <digits>
長い [整数, 文字列] int64 パターン <digits>
短い [整数, 文字列] int16 パターン <digits>
バイト [整数, 文字列] uint8 パターン <digits>
浮動小数 [数値,文字列] 浮動小数 パターン <digits with decimal >
ダブル [数値,文字列] ダブル パターン <digits with decimal >
小数点 [数値,文字列] ダブル パターン <digits with decimal >

type フィールドに配列値を指定できない OpenAPI 3.0 または OpenAPI v2 ドキュメントを生成するようにアプリが構成されている場合、type フィールドは削除されます。

NumberHandling プロパティが JsonNumberHandling.Strict に設定されている場合、数値型は次のようにマップされます。

C# 型 OpenAPI type OpenAPI format
整数 (int) 整数 int32
長い 整数 int64
短い 整数 int16
バイト 整数 uint8
浮動小数 数値 浮動小数
ダブル 数値 ダブル
小数点 数値 ダブル

文字列型

次の表は、生成された OpenAPI ドキュメントの string 型プロパティに C# 型がどのようにマップされるかを示しています。

C# 型 OpenAPI type OpenAPI format その他のアサーション
ひも ひも
焦げる ひも 焦げる 最小長さ: 1, 最大長さ: 1
byte[] ひも バイト
DateTimeOffset (日付と時刻のオフセット) ひも 日付と時間
日付のみ ひも 日付
TimeOnly ひも 時間
うり ひも URI
GUID ひも ユニバーサリー・ユニーク・アイデンティファイア (UUID)

その他の型

その他の C# 型は、次の表に示すように、生成された OpenAPI ドキュメントで表されます。

C# 型 OpenAPI type OpenAPI format
ブール (bool) ブーリアン
オブジェクト 省略
動的 省略

属性を使用してメタデータを追加する

ASP.NET は、クラスプロパティまたはレコードプロパティの属性のメタデータを使用して、生成されたスキーマの対応するプロパティにメタデータを設定します。

次の表は、生成されたスキーマのメタデータを提供する System.ComponentModel 名前空間の属性をまとめたものです。

属性 説明
[Description] スキーマ内のプロパティの description を設定します。
[Required] プロパティをスキーマ内の required としてマークします。
[DefaultValue] スキーマ内のプロパティの default 値を設定します。
[Range] 整数または数値の minimummaximum の値を設定します。
[MinLength] 文字列のminLengthまたは配列のminItemsを設定します。
[MaxLength] 文字列のmaxLengthまたは配列のmaxItemsを設定します。
[RegularExpression] 文字列の pattern を設定します。

コントローラー ベースのアプリでは、これらの属性によってフィルターが操作に追加され、入力データが制約を満たしていることに注意します。 最小限の API では、これらの属性によって生成されたスキーマのメタデータが設定されますが、検証は、エンドポイント フィルター、ルート ハンドラーのロジック、またはサード パーティのパッケージを介して明示的に実行する必要があります。

属性は、レコード定義のパラメーター リスト内のパラメーターに配置することもできますが、 property 修飾子を含める必要があります。 次に例を示します。

public record Todo(
    [property: Required]
    [property: Description("The unique identifier for the todo")]
    int Id,
    [property: Description("The title of the todo")]
    [property: MaxLength(120)]
    string Title,
    [property: Description("Whether the todo has been completed")]
    bool Completed
) {}

生成されたスキーマのメタデータのその他のソース

必須

クラス、構造体、またはレコードでは、 [Required] 属性または 必要な 修飾子を持つプロパティは、対応するスキーマで常に required されます。

クラス、構造体、またはレコードのコンストラクター (暗黙的および明示的) に基づいて、他のプロパティも必要になる場合があります。

  • 1 つのパブリック コンストラクターを持つクラスまたはレコード クラスの場合、対応するスキーマでは、コンストラクターのパラメーターと同じ型と名前 (大文字と小文字を区別しない一致) を持つプロパティが必要です。
  • 複数のパブリック コンストラクターを持つクラスまたはレコード クラスの場合、他のプロパティは必要ありません。
  • 構造体またはレコード構造体の場合、C# は常に構造体の暗黙的なパラメーターなしのコンストラクターを定義するため、他のプロパティは必要ありません。

イーナム

C# の列挙型は整数ベースですが、JSON では [JsonConverter]JsonStringEnumConverter を使用して文字列として表すことができます。 列挙型が JSON で文字列として表される場合、生成されるスキーマには列挙型の文字列値を持つ enum プロパティが含まれます。

次の例では、json で JsonStringEnumConverter を使用して列挙型を文字列として表す方法を示します。

[JsonConverter(typeof(JsonStringEnumConverter<DayOfTheWeekAsString>))]
public enum DayOfTheWeekAsString
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
}

特殊なケースは、列挙型に [Flags] 属性がある場合です。これは、列挙型をビット フィールドとして扱うことができることを示します。つまり、フラグのセットです。 enumを持つフラグ[JsonConverterAttribute]は、生成されたスキーマでtype: stringプロパティを持たないenumとして定義されます。 値は列挙値の任意の組み合わせになる可能性があるため、 enum プロパティは生成されません。 たとえば、次の enum は、 "Pepperoni, Sausage""Sausage, Mushrooms, Anchovies"などの値を持つことができます。

[Flags, JsonConverter(typeof(JsonStringEnumConverter<PizzaToppings>))]
public enum PizzaToppings { 
    Pepperoni = 1,
    Sausage = 2,
    Mushrooms = 4,
    Anchovies = 8
}

[JsonConverter] のない列挙型は、生成されたスキーマで type: integer として定義されます。

注:[AllowedValues] 属性では、プロパティの enum 値は設定されません。

をグローバルに設定する方法が示されます。

null 許容

null 許容値または参照型として定義されたプロパティは、生成されたスキーマに type キーワードと共に表示されます。このキーワードの値は、型の 1 つとして null を含む配列です。 これは、Nullable プロパティの有効な値として System.Text.Json を受け入れる、null 逆シリアライザーの既定の動作と一致します。

たとえば、 string? として定義された C# プロパティは、生成されたスキーマで次のように表されます。

  "nullableString": {
    "description": "A property defined as string?",
    "type": [
      "null",
      "string"
    ]
  },

OpenAPI v3.0 または OpenAPI v2 ドキュメントを生成するようにアプリが構成されている場合、これらの OpenAPI バージョンでは nullable: true フィールドを配列にできないため、生成されたスキーマに null 許容値または参照型がtype

追加プロパティ

既定では、スキーマは additionalProperties アサーションなしで生成されます。これは、true の既定値を意味します。 これは、System.Text.Json 逆シリアライザーの既定の動作と一致し、JSON オブジェクト内の追加のプロパティは自動的に無視されます。

スキーマの追加プロパティに特定の型の値のみを含める必要がある場合は、プロパティまたはクラスを Dictionary<string, type> として定義します。 ディクショナリのキーの種類は string である必要があります。 これにより、必要な値型として "type" のスキーマを指定する additionalProperties を持つスキーマが生成されます。

ポリモーフィック型

親クラスの [JsonPolymorphic] 属性と [JsonDerivedType] 属性を使用して、ポリモーフィック型の識別子フィールドとサブタイプを指定します。

[JsonDerivedType] は、サブクラスの特定の識別子値を指定する列挙型を使用して、各サブクラスのスキーマに識別子フィールドを追加します。 この属性は、識別子の値を設定するために、各派生クラスのコンストラクターも変更します。

[JsonPolymorphic] 属性を持つ抽象クラスにはスキーマに discriminator フィールドがありますが、[JsonPolymorphic] 属性を持つ具象クラスには discriminator フィールドがありません。 OpenAPI では、識別子プロパティをスキーマの必須プロパティにする必要がありますが、識別子プロパティは具象基底クラスで定義されていないため、スキーマに discriminator フィールドを含めることはできません。

スキーマ トランスフォーマーを使用してメタデータを追加する

スキーマ トランスフォーマーを使用すると、既定のメタデータをオーバーライドしたり、example 値などのメタデータを生成されたスキーマに追加したりできます。 詳細については、「スキーマ トランスフォーマーの使用」をご覧ください。

JSON シリアル化オプションをグローバルに設定する

次のコードでは、最小限の API とコントローラー ベースの API に対して、いくつかの JSON オプションをグローバルに構成します。

using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.Json;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();

builder.Services.Configure<JsonOptions>(options =>
{
    options.SerializerOptions.Converters.Add(
        new JsonStringEnumConverter<DayOfTheWeekAsString>());
    options.SerializerOptions.DefaultIgnoreCondition =
        JsonIgnoreCondition.WhenWritingNull;
    options.SerializerOptions.PropertyNamingPolicy =
        JsonNamingPolicy.CamelCase;

});

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(
            new JsonStringEnumConverter<DayOfTheWeekAsString>());
        options.JsonSerializerOptions.DefaultIgnoreCondition =
            JsonIgnoreCondition.WhenWritingNull;
        options.JsonSerializerOptions.PropertyNamingPolicy =
            JsonNamingPolicy.CamelCase;
    });

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

app.MapGet("/", () =>
{
    var day = DayOfTheWeekAsString.Friday;
    return Results.Json(day);
});

app.MapPost("/", (DayOfTheWeekAsString day) =>
{
    return Results.Json($"Received: {day}");
});

app.UseRouting();
app.MapControllers();

app.Run();

MVC JSON オプションとグローバル JSON オプション

次の表は、MVC JSON オプションとグローバルな最小 API JSON オプションの主な違いを示しています。

アスペクト MVC JSON オプション グローバル JSON オプション
スコープ MVC コントローラーとエンドポイントに限定されます。 最小限の API と OpenAPI ドキュメント。
構成 AddControllers().AddJsonOptions() Configure<JsonOptions>()
目的 API での JSON 要求と応答のシリアル化と逆シリアル化を処理します。 最小限の API と OpenAPI スキーマのグローバル JSON 処理を定義します。
OpenAPI への影響 無し OpenAPI スキーマの生成に直接影響します。

その他のリソース

ASP.NET は、Web アプリのエンドポイントからメタデータを収集し、それを使用して OpenAPI ドキュメントを生成します。

コントローラー ベースのアプリでは、コントローラーに[EndpointDescription]属性があるときに、[HttpPost][Produces][ApiController]などの属性からメタデータが収集されます。

最小限の API では、メタデータは属性から収集できますが、ルート ハンドラーから TypedResults を返すなどの拡張メソッドやその他の戦略を使用して設定することもできます。

次の表に、収集されるメタデータと、それを設定するための戦略の概要を示します。

メタデータ 属性 拡張メソッド その他の戦略
まとめ [EndpointSummary] WithSummary
説明 [EndpointDescription] WithDescription
タグ [Tags] WithTags
operationId [EndpointName] WithName
パラメーター [FromQuery][FromRoute][FromHeader][FromForm]
パラメーターの説明 [Description]
リクエストボディ [FromBody] Accepts
応答 [Produces] ProducesProducesProblem TypedResults
エンドポイントの除外 [ExcludeFromDescription][ApiExplorerSettings] ExcludeFromDescription

ASP.NET Core では、XML ドキュメントのコメントからメタデータは収集されません。

次のセクションでは、生成された OpenAPI ドキュメントをカスタマイズするためにアプリにメタデータを含める方法を示します。

要約と説明

エンドポイントの概要と説明は、[EndpointSummary] 属性と [EndpointDescription] 属性を使用して、または Minimal API で、WithSummaryWithDescription 拡張メソッドを使用して設定できます。

次のサンプルでは、概要と説明を設定するためのさまざまな方法を示します。

属性は app.MapGet メソッドではなくデリゲート メソッドに配置されることに注意してください。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithSummary("This is a summary.")
    .WithDescription("This is a description.");

app.MapGet("/attributes",
    [EndpointSummary("This is a summary.")]
    [EndpointDescription("This is a description.")]
    () => "Hello world!");

タグ

OpenAPI では、分類の形式として各エンドポイントでタグを指定することをサポートしています。

Minimal API では、[Tags] 属性または WithTags 拡張メソッドを使用してタグを設定できます。

次のサンプルでは、タグを設定するためのさまざまな戦略を示します。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithTags("todos", "projects");

app.MapGet("/attributes",
    [Tags("todos", "projects")]
    () => "Hello world!");

operationId

OpenAPI では、操作の一意の識別子または名前として、各エンドポイントの operationId がサポートされています。

Minimal API では、[EndpointName] 属性または WithName 拡張メソッドを使用して operationId を設定できます。

次のサンプルでは、operationIdを設定するためのさまざまな戦略を説明します。

app.MapGet("/extension-methods", () => "Hello world!")
    .WithName("FromExtensionMethods");

app.MapGet("/attributes",
    [EndpointName("FromAttributes")]
    () => "Hello world!");

パラメーター

OpenAPI では、API によって使用されるパス、クエリ文字列、ヘッダー、cookie パラメーターの注釈付けをサポートします。

フレームワークは、ルート ハンドラーのシグネチャに基づいて、要求パラメーターの型を自動的に推論します。

[Description] 属性を使用して、パラメーターの説明を指定できます。

[Description]属性は MVC アプリでは機能しますが、現時点では最小限の API アプリでは機能しません。 詳細については、「DescriptionのパラメーターProducesResponseTypeAttribute最小限の API アプリでは機能しません (dotnet/aspnetcore #60518)」を参照してください。

リクエストの本文を説明する

OpenAPI の requestBody フィールドには、サポートされているコンテンツ タイプや本文コンテンツのスキーマなど、API クライアントがサーバーに送信できる要求の本文が記述されています。

エンドポイント ハンドラー メソッドが要求本文からバインドされたパラメーターを受け入れると、ASP.NET Core は OpenAPI ドキュメント内の操作に対応する requestBody を生成します。 要求本文のメタデータは、属性または拡張メソッドを使用して指定することもできます。 追加のメタデータは、 document トランスフォーマー または 操作トランスフォーマーで設定できます。

エンドポイントが要求本文にバインドされたパラメーターを定義せず、代わりに HttpContext から直接要求本文を使用する場合、ASP.NET Core は要求本文メタデータを指定するメカニズムを提供します。 これは、要求本文をストリームとして処理するエンドポイントの一般的なシナリオです。

一部の要求本文メタデータは、ルート ハンドラー メソッドの FromBody または FromForm パラメーターから決定できます。

要求本文の説明は、パラメーターの [Description] 属性を使用して、 FromBody または FromFormで設定できます。

FromBody パラメーターが null 非許容で、EmptyBodyBehaviorAllow 属性のFromBodyに設定されていない場合は、要求本文が必要であり、requiredrequestBody フィールドは、生成された OpenAPI ドキュメントでtrueに設定されます。 フォーム本体は常に必須であり、 requiredtrueに設定します。

document トランスフォーマーまたは操作トランスフォーマーを使用してexampleexamples、またはencodingフィールドを設定したり、生成された OpenAPI ドキュメントの要求本文の仕様拡張を追加したりできます。

要求本文のメタデータを設定するためのその他のメカニズムは、開発するアプリの種類によって異なります。以降のセクションで説明します。

生成された OpenAPI ドキュメント内の要求本文のコンテンツ タイプは、要求本文にバインドされているパラメーターの型、または Accepts 拡張メソッドで指定されたパラメーターの型から決定されます。 既定では、 FromBody パラメーターのコンテンツ タイプは application/json され、 FromForm パラメーターのコンテンツ タイプは multipart/form-data または application/x-www-form-urlencodedされます。

これらの既定のコンテンツ タイプのサポートは最小限の API に組み込まれており、その他のコンテンツ タイプはカスタム バインドを使用して処理できます。 詳細については、最小限の API ドキュメントの Custom バインド トピックを参照してください。

要求本文に異なるコンテンツ タイプを指定するには、いくつかの方法があります。 FromBody パラメーターの型がIEndpointParameterMetadataProviderを実装する場合、ASP.NET Core はこのインターフェイスを使用して、要求本文のコンテンツ タイプを決定します。 フレームワークでは、このインターフェイスの PopulateMetadata メソッドを使用して、要求本文の本文コンテンツのコンテンツ タイプと型を設定します。 たとえば、Todo または application/xml コンテンツ タイプのいずれかを受け入れるtext/xml クラスは、IEndpointParameterMetadataProviderを使用してフレームワークにこの情報を提供できます。

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        builder.Metadata.Add(new AcceptsMetadata(["application/xml", "text/xml"], typeof(Todo)));
    }
}

Accepts拡張メソッドを使用して、要求本文のコンテンツ タイプを指定することもできます。 次の例では、エンドポイントは要求本文で Todo オブジェクトを受け入れ、想定されるコンテンツ タイプは application/xml となります。

app.MapPut("/todos/{id}", (int id, Todo todo) => ...)
    .Accepts<Todo>("application/xml");

application/xmlは組み込みのコンテンツ タイプではないため、Todo クラスはIBindableFromHttpContext<TSelf> インターフェイスを実装して、要求本文のカスタム バインドを提供する必要があります。 次に例を示します。

public class Todo : IBindableFromHttpContext<Todo>
{
    public static async ValueTask<Todo?> BindAsync(HttpContext context, ParameterInfo parameter)
    {
        var xmlDoc = await XDocument.LoadAsync(context.Request.Body, LoadOptions.None, context.RequestAborted);
        var serializer = new XmlSerializer(typeof(Todo));
        return (Todo?)serializer.Deserialize(xmlDoc.CreateReader());
    }
}

エンドポイントで要求本文にバインドされているパラメーターが定義されていない場合は、 Accepts 拡張メソッドを使用して、エンドポイントが受け入れるコンテンツ タイプを指定します。

AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A<>を複数回指定した場合、最後のメタデータのみが使用されます。これらは結合されません。

応答の種類の説明

OpenAPI では、API から返される応答の記述を提供できます。 ASP.NET Core には、エンドポイントの応答メタデータを設定するためのいくつかの戦略が用意されています。 設定できる応答メタデータには、状態コード、応答本文の種類、応答のコンテンツ タイプが含まれます。 OpenAPI の応答には、説明、ヘッダー、リンク、例などの追加のメタデータが含まれる場合があります。 この追加のメタデータは、 document トランスフォーマー または 操作トランスフォーマーで設定できます。

応答メタデータを設定するための具体的なメカニズムは、開発するアプリの種類によって異なります。

最小 API アプリでは、ASP.NET Core では、エンドポイントの拡張メソッドによって追加された応答メタデータ、ルート ハンドラーの属性、およびルート ハンドラーの戻り値の型を抽出できます。

  • Produces拡張メソッドをエンドポイントで使用して、状態コード、応答本文の種類、エンドポイントからの応答のコンテンツ タイプを指定できます。
  • [ProducesResponseType]またはProducesResponseTypeAttribute<T>属性を使用して、応答本文の型を指定できます。
  • ルート ハンドラーを使用して、応答本文の型とコンテンツ タイプを指定する IEndpointMetadataProvider を実装する型を返すことができます。
  • エンドポイントの ProducesProblem 拡張メソッドを使用して、エラー応答の状態コードとコンテンツ タイプを指定できます。

ProducesおよびProducesProblem拡張メソッドは、RouteHandlerBuilderRouteGroupBuilderの両方でサポートされることに注意してください。 これにより、たとえば、グループ内のすべての操作に対して一般的な一連のエラー応答を定義できます。

上記のいずれかの方法で指定されていない場合、次のようになります。

  • 応答の状態コードの既定値は 200 です。
  • 応答本文のスキーマは、エンドポイント メソッドの暗黙的または明示的な戻り値の型 (たとえば、TTask<TResult>から) から推論できます。それ以外の場合は、指定されていないと見なされます。
  • 指定または推論された応答本文のコンテンツタイプは "application/json" です。

Minimal API では、 Produces 拡張メソッドと [ProducesResponseType] 属性によってエンドポイントの応答メタデータのみが設定されます。 エンドポイントの動作は変更または制約されません。エンドポイントの動作は、メタデータで指定された状態コードまたは応答本文の種類とは異なる場合があり、コンテンツ タイプは、属性または拡張メソッドで指定されたコンテンツ タイプに関係なく、ルート ハンドラー メソッドの戻り値の型によって決定されます。

Produces拡張メソッドでは、エンドポイントの応答の種類を指定できます。既定の状態コードは 200 で、既定のコンテンツ タイプは application/json。 次に例を示します。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

[ProducesResponseType]を使用して、応答メタデータをエンドポイントに追加できます。 次の例に示すように、ルートを作成するためのメソッド呼び出しではなく、ルート ハンドラー メソッドに属性が適用されることに注意してください。

app.MapGet("/todos",
    [ProducesResponseType<List<Todo>>(200)]
    async (TodoDb db) => await db.Todos.ToListAsync());

エンドポイントのルート ハンドラーの実装で TypedResults を使用すると、エンドポイントに対する応答の型のメタデータが自動的に含まれます。 たとえば、以下のコードは、200 コンテンツ タイプでの application/json 状態コードの応答で、エンドポイントに自動的に注釈を付けます。

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync();
    return TypedResults.Ok(todos);
});

IEndpointMetadataProviderを実装した型のみがOpenAPIドキュメント内にresponsesエントリを作成します。 TypedResults エントリを生成するresponses ヘルパー メソッドの一部の一覧を次に示します。

TypedResults 補助的なメソッド 状態コード
Ok() 200
作成済み() 201
CreatedAtRoute() 201
承認済み 2:02
AcceptedAtRoute() 2:02
コンテンツなし() 204
BadRequest() 400
ValidationProblem() 400
NotFound(見つかりません) 404
衝突() 409
UnprocessableEntity(処理できないエンティティ) 422

NoContentを除くすべてのメソッドには、応答本文の型を指定するジェネリック オーバーロードがあります。

エンドポイント メタデータを設定し、ルート ハンドラーから返すクラスを実装できます。

ProblemDetails の応答を設定する

ProblemDetails 応答を返す可能性があるエンドポイントの応答の種類を設定する場合は、次を使用してエンドポイントに適切な応答メタデータを追加できます。

ProblemDetails 応答を返すように最小限の API アプリを構成する方法の詳細については、「最小限の API でエラーを処理する を参照してください

複数応答の種類

エンドポイントがさまざまなシナリオでさまざまな種類の応答を返すことができる場合は、次の方法でメタデータを指定できます。

  • 次の例に示すように、Produces 拡張メソッドを複数回呼び出します。

    app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
             await db.Todos.FindAsync(id) 
             is Todo todo
             ? Results.Ok(todo) 
             : Results.NotFound())
       .Produces<Todo>(StatusCodes.Status200OK)
       .Produces(StatusCodes.Status404NotFound);
    
  • 次の例に示すように、シグネチャで Results<TResult1,TResult2,TResult3,TResult4,TResult5,TResult6> を、ハンドラーの本体で TypedResults を使用します。

    app.MapGet("/book/{id}", Results<Ok<Book>, NotFound> 
        (int id, List<Book> bookList) =>
        {
            return bookList.FirstOrDefault((i) => i.Id == id) is Book book
            ? TypedResults.Ok(book)
            : TypedResults.NotFound();
        });
    

    Results<TResult1,TResult2,TResultN> 共用体型は、ルート ハンドラーが IResult を実装する複数の具象型を返し、IEndpointMetadataProvider を実装するそれらの型はいずれもエンドポイントのメタデータに寄与することを宣言します。

    共用体型は、暗黙的なキャスト演算子を実装します。 これらの演算子により、コンパイラはジェネリック引数で指定されている型を共用体型のインスタンスに自動的に変換できるようになります。 この機能にはさらに、ルート ハンドラーからそうすることが宣言されている結果のみが返されることがコンパイル時にチェックされるという利点があります。 ジェネリック引数の 1 つとして宣言されていない型を Results<TResult1,TResult2,TResultN> に返そうとすると、コンパイル エラーが発生します。

生成されたドキュメントからエンドポイントを除外する

既定では、アプリで定義されているすべてのエンドポイントは生成された OpenAPI ファイルに文書化されますが、エンドポイントは属性または拡張メソッドを使用してドキュメントから除外できます。

除外する必要があるエンドポイントを指定するメカニズムは、開発するアプリの種類によって異なります。

最小限の API では、OpenAPI ドキュメントから特定のエンドポイントを除外するための 2 つの戦略がサポートされています。

次のサンプルでは、生成された OpenAPI ドキュメントから指定されたエンドポイントを除外するためのさまざまな方法を示します。

app.MapGet("/extension-method", () => "Hello world!")
    .ExcludeFromDescription();

app.MapGet("/attributes",
    [ExcludeFromDescription]
    () => "Hello world!");

データ型の OpenAPI メタデータを含める

要求または応答本文で使用される C# クラスまたはレコードは、生成された OpenAPI ドキュメントのスキーマとして表されます。 既定では、スキーマではパブリック プロパティのみが表されますが、フィールドのスキーマ プロパティも作成する JsonSerializerOptions があります。

PropertyNamingPolicy がキャメルケースに設定されている場合 (これは ASP.NET Web アプリケーションの既定値です)、スキーマ内のプロパティ名は、クラスまたはレコードプロパティ名のキャメルケース形式です。 [JsonPropertyName] は、個々のプロパティでスキーマ内のプロパティの名前を指定するために使用できます。

種類と形式

JSON スキーマ ライブラリは、標準の C# 型を OpenAPI typeformat に次のようにマップします。

C# 型 OpenAPI type OpenAPI format
整数 (int) 整数 int32
長い 整数 int64
短い 整数 int16
バイト 整数 uint8
浮動小数 数値 浮動小数
ダブル 数値 ダブル
小数点 数値 ダブル
ブール (bool) ブーリアン
ひも ひも
焦げる ひも 焦げる
byte[] ひも バイト
DateTimeOffset (日付と時刻のオフセット) ひも 日付と時間
日付のみ ひも 日付
TimeOnly ひも 時間
うり ひも URI
GUID ひも ユニバーサリー・ユニーク・アイデンティファイア (UUID)
オブジェクト 省略
動的 省略

オブジェクト型と動的型には、no 型が OpenAPI で定義されていることに注意してください。これは、int や string などのプリミティブ型を含む任意の型のデータを含むことができるためです。

typeformat は、スキーマ トランスフォーマーで設定することもできます。 たとえば、10 進型の formatdecimal の代わりに double にするとします。

属性を使用してメタデータを追加する

ASP.NET は、クラスプロパティまたはレコードプロパティの属性のメタデータを使用して、生成されたスキーマの対応するプロパティにメタデータを設定します。

次の表は、生成されたスキーマのメタデータを提供する System.ComponentModel 名前空間の属性をまとめたものです。

属性 説明
[Description] スキーマ内のプロパティの description を設定します。
[Required] プロパティをスキーマ内の required としてマークします。
[DefaultValue] スキーマ内のプロパティの default 値を設定します。
[Range] 整数または数値の minimummaximum の値を設定します。
[MinLength] 文字列のminLengthまたは配列のminItemsを設定します。
[MaxLength] 文字列のmaxLengthまたは配列のmaxItemsを設定します。
[RegularExpression] 文字列の pattern を設定します。

コントローラー ベースのアプリでは、これらの属性によってフィルターが操作に追加され、入力データが制約を満たしていることに注意します。 最小限の API では、これらの属性によって生成されたスキーマのメタデータが設定されますが、検証は、エンドポイント フィルター、ルート ハンドラーのロジック、またはサード パーティのパッケージを介して明示的に実行する必要があります。

属性は、レコード定義のパラメーター リスト内のパラメーターに配置することもできますが、 property 修飾子を含める必要があります。 次に例を示します。

public record Todo(
    [property: Required]
    [property: Description("The unique identifier for the todo")]
    int Id,
    [property: Description("The title of the todo")]
    [property: MaxLength(120)]
    string Title,
    [property: Description("Whether the todo has been completed")]
    bool Completed
) {}

生成されたスキーマのメタデータのその他のソース

必須

クラス、構造体、またはレコードでは、 [Required] 属性または 必要な 修飾子を持つプロパティは、対応するスキーマで常に required されます。

クラス、構造体、またはレコードのコンストラクター (暗黙的および明示的) に基づいて、他のプロパティも必要になる場合があります。

  • 1 つのパブリック コンストラクターを持つクラスまたはレコード クラスの場合、対応するスキーマでは、コンストラクターのパラメーターと同じ型と名前 (大文字と小文字を区別しない一致) を持つプロパティが必要です。
  • 複数のパブリック コンストラクターを持つクラスまたはレコード クラスの場合、他のプロパティは必要ありません。
  • 構造体またはレコード構造体の場合、C# は常に構造体の暗黙的なパラメーターなしのコンストラクターを定義するため、他のプロパティは必要ありません。

イーナム

C# の列挙型は整数ベースですが、JSON では [JsonConverter]JsonStringEnumConverter を使用して文字列として表すことができます。 列挙型が JSON で文字列として表される場合、生成されるスキーマには列挙型の文字列値を持つ enum プロパティが含まれます。

次の例では、json で JsonStringEnumConverter を使用して列挙型を文字列として表す方法を示します。

[JsonConverter(typeof(JsonStringEnumConverter<DayOfTheWeekAsString>))]
public enum DayOfTheWeekAsString
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
}

特殊なケースは、列挙型に [Flags] 属性がある場合です。これは、列挙型をビット フィールドとして扱うことができることを示します。つまり、フラグのセットです。 [JsonConverterAttribute]を持つフラグ列挙型は、type: stringプロパティを持たない生成されたスキーマでenumとして定義されます。これは、値が列挙値の任意の組み合わせになる可能性があるためです。 たとえば、次の列挙型:

[Flags, JsonConverter(typeof(JsonStringEnumConverter<PizzaToppings>))]
public enum PizzaToppings { Pepperoni = 1, Sausage = 2, Mushrooms = 4, Anchovies = 8 }

には、 "Pepperoni, Sausage""Sausage, Mushrooms, Anchovies"などの値が含まれます。

[JsonConverter] のない列挙型は、生成されたスキーマで type: integer として定義されます。

注:[AllowedValues] 属性では、プロパティの enum 値は設定されません。

null 許容

null 許容値または参照型として定義されたプロパティは、生成されたスキーマに nullable: true があります。 これは、Nullable プロパティの有効な値として System.Text.Json を受け入れる、null 逆シリアライザーの既定の動作と一致します。

追加プロパティ

既定では、スキーマは additionalProperties アサーションなしで生成されます。これは、true の既定値を意味します。 これは、System.Text.Json 逆シリアライザーの既定の動作と一致し、JSON オブジェクト内の追加のプロパティは自動的に無視されます。

スキーマの追加プロパティに特定の型の値のみを含める必要がある場合は、プロパティまたはクラスを Dictionary<string, type> として定義します。 ディクショナリのキーの種類は string である必要があります。 これにより、必要な値型として "type" のスキーマを指定する additionalProperties を持つスキーマが生成されます。

ポリモーフィック型

親クラスの [JsonPolymorphic] 属性と [JsonDerivedType] 属性を使用して、ポリモーフィック型の識別子フィールドとサブタイプを指定します。

[JsonDerivedType] は、サブクラスの特定の識別子値を指定する列挙型を使用して、各サブクラスのスキーマに識別子フィールドを追加します。 この属性は、識別子の値を設定するために、各派生クラスのコンストラクターも変更します。

[JsonPolymorphic] 属性を持つ抽象クラスにはスキーマに discriminator フィールドがありますが、[JsonPolymorphic] 属性を持つ具象クラスには discriminator フィールドがありません。 OpenAPI では、識別子プロパティをスキーマの必須プロパティにする必要がありますが、識別子プロパティは具象基底クラスで定義されていないため、スキーマに discriminator フィールドを含めることはできません。

スキーマ トランスフォーマーを使用してメタデータを追加する

スキーマ トランスフォーマーを使用すると、既定のメタデータをオーバーライドしたり、example 値などのメタデータを生成されたスキーマに追加したりできます。 詳細については、「スキーマ トランスフォーマーの使用」をご覧ください。

その他のリソース