You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swagger枚举字符串化及成员隐藏后UI无法正常使用的解决方案求助

枚举Schema过滤器问题解决方案

问题描述

编写了如下Swagger Schema过滤器,用于隐藏标记了OpenApiIgnoreEnumAttribute的枚举成员,同时支持切换使用枚举值或枚举名称:

public class OpenApiIgnoreEnumSchemaFilter : ISchemaFilter
{
    private readonly bool _useNames;

    public OpenApiIgnoreEnumSchemaFilter(bool useNames = false)
    {
        _useNames = useNames;
    }

    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (!context.Type.IsEnum && !(Nullable.GetUnderlyingType(context.Type)?.IsEnum ?? false))
        {
            return;
        }

        Type type = (context.Type.IsEnum ? context.Type : Nullable.GetUnderlyingType(context.Type));
        List<IOpenApiAny> list = new List<IOpenApiAny>();
        string[] names = Enum.GetNames(type);
        int[] values = Enum.GetValues(type).Cast<int>().ToArray();
        foreach (var (text, value) in names.Select((string name, int index) => (name, values[index])).ToList())
        {
            if (!type.GetMember(text)[0].GetCustomAttributes<OpenApiIgnoreEnumAttribute>().Any())
            {
                IOpenApiAny item;
                if (!_useNames)
                {
                    IOpenApiAny openApiAny = new OpenApiInteger(value);
                    item = openApiAny;
                }
                else
                {
                    IOpenApiAny openApiAny = new OpenApiString(text);
                    item = openApiAny;
                }

                list.Add(item);
            }
        }

        schema.Enum = list;
    }
}

但当构造函数传入true(即使用枚举名称)时,在SwaggerUI下拉菜单选择字符串化枚举值,系统提示仅允许整数值,需要保留原有功能的同时解决该问题。

问题原因

过滤器仅替换了schema.Enum的内容,但未同步修改Schema的Type和Format属性。默认情况下枚举对应的Schema类型是integer,即使枚举项换成字符串,Swagger仍会按整数类型校验输入,导致报错。

修改后的过滤器代码

public class OpenApiIgnoreEnumSchemaFilter : ISchemaFilter
{
    private readonly bool _useNames;

    public OpenApiIgnoreEnumSchemaFilter(bool useNames = false)
    {
        _useNames = useNames;
    }

    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (!context.Type.IsEnum && !(Nullable.GetUnderlyingType(context.Type)?.IsEnum ?? false))
        {
            return;
        }

        Type enumType = context.Type.IsEnum ? context.Type : Nullable.GetUnderlyingType(context.Type);
        List<IOpenApiAny> enumItems = new List<IOpenApiAny>();
        string[] enumNames = Enum.GetNames(enumType);
        int[] enumValues = Enum.GetValues(enumType).Cast<int>().ToArray();

        foreach (var (name, value) in enumNames.Select((n, idx) => (n, enumValues[idx])))
        {
            // 跳过标记了忽略属性的枚举成员
            if (enumType.GetMember(name)[0].GetCustomAttributes<OpenApiIgnoreEnumAttribute>().Any())
            {
                continue;
            }

            IOpenApiAny enumItem = _useNames 
                ? (IOpenApiAny)new OpenApiString(name) 
                : new OpenApiInteger(value);
            enumItems.Add(enumItem);
        }

        schema.Enum = enumItems;

        // 根据useNames设置对应的Schema类型
        if (_useNames)
        {
            schema.Type = "string";
            schema.Format = null; // 清除默认的integer格式
            // 如果有默认值,同步转换为字符串类型
            if (schema.Default is OpenApiInteger defaultInt)
            {
                var defaultName = Enum.GetName(enumType, defaultInt.Value);
                schema.Default = new OpenApiString(defaultName);
            }
        }
        else
        {
            // 保持默认的整数类型设置
            schema.Type = "integer";
            schema.Format = "int32";
        }
    }
}

关键修改说明

  • 当_useNames=true时,将schema.Type设为"string"并清空Format,让Swagger识别该字段为字符串类型
  • 同步处理Schema的默认值:如果原来的默认值是整数类型,转换为对应的枚举名称字符串,保持数据一致性
  • 优化代码结构,简化枚举项的创建逻辑

内容的提问来源于stack exchange,提问作者Marek M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:25:30