自定义生成的模型名称 - Swagger UI

问题描述 投票:0回答:5

我正在尝试调整自动生成的 Swagger 定义中使用的模型的“displayName”。

这只会影响 Swagger 名称,这意味着代码中的命名空间将保持不变,而从 Swagger UI 查看模型时,您会看到自定义名称。

目前,从代码返回的模型名称是一个命名空间,看起来像这样:

b.c.d.e.f
,我想向代码添加一个属性并“屏蔽”Swagger 文档的名称,以便当文档/ Swagger 定义生成,它将显示为
CustomSwaggerName

我有一些使用工具的 API (C#),包括

Swashbuckle
(首选)和
SwaggerGen
,但现在,如果可能的话,我只想让它在其中任何一个中工作。

我尝试使用看起来正确的属性:

[ResponseType(typeof(Company)),DisplayName("NewCompany")]
[SwaggerResponse(200,"NewCompany",typeof(object))]

没有运气。我还浏览了 SwashBuckle git 存储库,希望能找到一些东西。

这张图片应该有助于进一步解释我想要实现的目标。 enter image description here

我知道这可能看起来是一个奇怪的用例,但它是为我们的 AWS API Gateway 自动化编写的工具,它将使用 Swagger 定义进行一些比较。

c# swagger swagger-ui swashbuckle swagger-codegen
5个回答
28
投票

(.net core 的帐户:)
我会将类的显示属性与自定义的 swagger 模式结合起来:

[DisplayName("NewCompany")]
public class Company
{
}

然后在启动中:

services.AddSwaggerGen(c =>
{                     
    c.CustomSchemaIds(x => x.GetCustomAttributes<DisplayNameAttribute>().SingleOrDefault().DisplayName);
});

另请参阅这个答案


6
投票

这是我的解决方案,基于@AGuyCalledGerald 提供的建议 - 谢谢!

它使用更明确的自定义属性而不是

DisplayName
,因此很清楚该属性的用途,如果该属性不存在,它将回退到默认命名策略。

助手/SwashbuckleHelpers.cs:

namespace MyProject.Helpers;

public static class SwashbuckleHelpers
{
    /// <summary>
    /// Direct copy of <see href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGeneratorOptions.cs">Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorOptions.DefaultSchemaIdSelector</see>.
    /// </summary>
    public static string DefaultSchemaIdSelector(Type modelType)
    {
        if (!modelType.IsConstructedGenericType) return modelType.Name.Replace("[]", "Array");

        var prefix = modelType.GetGenericArguments()
            .Select(genericArg => DefaultSchemaIdSelector(genericArg))
            .Aggregate((previous, current) => previous + current);

        return prefix + modelType.Name.Split('`').First();
    }
}

属性/CustomSwaggerSchemaIdAttribute.cs

namespace MyProject.Attributes;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class CustomSwaggerSchemaIdAttribute : Attribute
{
    public virtual string SchemaId { get; init; }

    public CustomSwaggerSchemaIdAttribute(string schemaId)
    {
        SchemaId = schemaId;
    }
}

程序.cs:

builder.Services.AddSwaggerGen(options =>
{
    ...
    options.CustomSchemaIds(t =>  t.GetCustomAttributes<CustomSwaggerSchemaIdAttribute>().SingleOrDefault()?.SchemaId ?? SwashbuckleHelpers.DefaultSchemaIdSelector(t));
});

用法示例:

[CustomSwaggerSchemaId("Customer")]
public class CustomerDto
{
    ...
}

2
投票

我已经使用了this解决方案并在评论中提出了建议。但 x.Name 在泛型类型的情况下返回过于冗长的名称。 Swashbuckle.Swagger 命名空间中有一个扩展方法,Swagger 默认使用该方法。我最终得到了下一个代码。

[DisplayName("NewCompany")]
public class Company
{
}

Startup.cs

using Swashbuckle.Swagger;

services.AddSwaggerGen(c =>
{        
    c.SchemaId(x => x.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault()?.DisplayName ?? x.FriendlyId());
});

1
投票

答案是:使用 IDocumentFilter:

private class ApplyDocumentFilter_ChangeCompany : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        if (swaggerDoc.definitions != null)
        {
            swaggerDoc.definitions.Add("Company123", swaggerDoc.definitions["Company"]);
        }
        if (swaggerDoc.paths != null)
        {
            swaggerDoc.paths["/api/Company"].get.responses["200"].schema.@ref = "#/definitions/Company123";
        }
    }
}

代码如下: https://github.com/heldersepu/SwashbuckleTest/commit/671ce648a7cc52290b4ad29ca540b476e65240e6

这是最终结果: http://swashbuckletest.azurewebsites.net/swagger/ui/index#!/Company/Company_Get


0
投票

如果使用 NSwag,这就是我所做的:

// Program.cs
builder.Services.AddOpenApiDocument(settings =>
{
    settings.SchemaSettings.SchemaNameGenerator = new PublicSchemaNameGenerator();
});
// PublicSchemaNameGenerator.cs
using System.ComponentModel;
using System.Reflection;
using NJsonSchema.Generation;

public class PublicSchemaNameGenerator : ISchemaNameGenerator
{
    public string Generate(Type type)
    {
        var attribute = type.GetCustomAttributes<DisplayNameAttribute>().FirstOrDefault();
        if (attribute is null) 
        {
            return type.Name;
        }

        return attribute.DisplayName;
    }
}

现在您可以在想要使用此名称的类型上添加属性

DisplayName("SomeName")

// SomeType.cs
using System.ComponentModel;

[DisplayName("Product")]
public class SomeType
{
}
© www.soinside.com 2019 - 2024. All rights reserved.