【问题标题】:Is it possible to expose the same Swagger JSON in both Swagger 2.0 and Open API 3 formats with Swashbuckle in ASP .NET Core?是否可以在 ASP .NET Core 中使用 Swashbuckle 在 Swagger 2.0 和 Open API 3 格式中公开相同的 Swagger JSON?
【发布时间】:2021-07-27 14:02:54
【问题描述】:

我们有一个仅适用于 Swagger 2.0 JSON 格式的旧版应用程序。对于我们希望使用 Open API 格式的其他所有内容。

Swashbuckle .NET Core 有什么方法可以在不同的 URL 下以不同格式公开 JSON?看起来UseSwagger 方法选项中的SerializeAsV2 属性对于所有端点都是全局的。

基本上我希望以下端点包含不同格式的相同 API 数据。

/swagger/v1/openapi/swagger.json
/swagger/v1/swagger2/swagger.json

【问题讨论】:

    标签: asp.net-core swashbuckle.aspnetcore


    【解决方案1】:

    另一种方法是拆分请求管道:

    // serve v3 from /swagger/v1/swagger.json
    app.UseSwagger(o => o.RouteTemplate = "swagger/{documentName}/swagger.json");
    
    // serve v2 from /swagger2/v1/swagger.json
    app.Map("/swagger2", swaggerApp => 
        swaggerApp.UseSwagger(options => {
            // note the dropped prefix "swagger/"
            options.RouteTemplate = "{documentName}/swagger.json";
            options.SerializeAsV2 = true;
        })
    );
    

    【讨论】:

    • 这真的很优雅,效果很好。谢谢!
    【解决方案2】:

    您可以将 OpenAPI 文档序列化为 V2 并自行提供。以SwaggerMiddleware为参考:

    第一次注册SwaggerGenerator

    services.AddTransient<SwaggerGenerator>();
    

    然后注入SwaggerGenerator 并构建文档。从端点或控制器提供它。您可以将版本作为路径参数来决定提供哪个版本。

    app.UseEndpoints(e =>
    {
        // ...
        e.MapGet("/swagger/{documentName}/swagger.{version}.json", context =>
        {
            var documentName = context.Request.RouteValues.GetValueOrDefault("documentName", null) as string;
            var version = context.Request.RouteValues.GetValueOrDefault("version", null) as string;
            if (documentName is null || version is null)
            {
                context.Response.StatusCode = StatusCodes.Status400BadRequest;
                return Task.CompletedTask;
            }
    
            // inject SwaggerGenerator
            var swaggerGenerator = context.RequestServices.GetRequiredService<SwaggerGenerator>();
            var doc = swaggerGenerator.GetSwagger(documentName);
    
            // serialize the document as json
            using var writer = new StringWriter(CultureInfo.InvariantCulture);
            var serializer = new OpenApiJsonWriter(writer);
            if (version == "v2")
            {
                doc.SerializeAsV2(serializer);
            }
            else
            {
                doc.SerializeAsV3(serializer);
            }
            var json = writer.ToString();
    
            // serve it as json
            context.Response.ContentType = MediaTypeNames.Application.Json;
            return context.Response.WriteAsync(json, new UTF8Encoding(false));
        });
    });
    

    当您访问/swagger/v1/openapi.v2.json 时,您将获得序列化为 v2 的 OpenAPI 文档。

    {
      "swagger": "2.0",
      "info": {
        "title": "ApiPlayground",
        "version": "1.0"
      },
      "paths": { ... }
    }
    

    /swagger/v1/openapi.v3.json 会给您序列化为 v3 的文档:

    {
      "openapi": "3.0.1",
      "info": {
        "title": "ApiPlayground",
        "version": "1.0"
      },
      "paths": { ... },
      "components": { ... }
    }
    

    【讨论】:

    • 我还需要调用UseSwagger() 方法吗?感谢您提供详细的示例。
    • 不,它可以保留,也可以完全删除。但是您可能需要更新SwaggerUI 中间件配置。 app.UseSwaggerUI(c =&gt; c.SwaggerEndpoint("/swagger/v1/swagger.v2.json", "ApiPlayground v1"));
    猜你喜欢
    • 2018-04-16
    • 2021-03-01
    • 1970-01-01
    • 2018-07-29
    • 2018-02-01
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多