ASP.NET Core 模型类类型转换,swagger 对不上

2023年9月19日 669点热度 0人点赞 0条评论
内容纲要

模型类:

    public class Test
    {
        [JsonConverter(typeof(string))]
        public int Value { get; set; }
    }

API 接口:

        [HttpPost("aaa")]
        public string AAA([FromBody] Test test)
        {
            return "11111111111";
        }

但是 Swagger 还是显示 int 类型,没有跟着 json 配置而变化。
所以我们需要配置 Swagger,显示转换类型之后正确的类型信息。

定义一个过滤器:

    /// <summary>
    /// Swagger 模型类过滤器
    /// </summary>
    public class MaomiSwaggerSchemaFilter : ISchemaFilter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="schema">Swagger 中的属性</param>
        /// <param name="context">模型类上下文</param>
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            // 模型类的类型
            var type = context.Type;

            // 如果 API 参数不是对象
            if (type.IsPrimitive || TypeInfo.GetTypeCode(type) != TypeCode.Object)
            {
                return;
            }

            // 如果 API 参数是对象类型

            // 获取类型的所有属性
            PropertyInfo[] ps = context.Type.GetProperties();

            // 获取 swagger 文件显示的所有属性
            // 注意文档属性是已经已经生成的,这里进行后期转换,替换为需要显示的类型
            foreach (var property in schema.Properties)
            {
                var p = ps.FirstOrDefault(x => x.Name.ToLower() == property.Key.ToLower());
                if (p == null) continue;
                var t = property.Value.Type;
                var converter = p.GetCustomAttribute<JsonConverterAttribute>();
                if (converter == null || converter.ConverterType == null) continue;

                var targetType = TypeInfo.GetTypeCode(converter.ConverterType);

                // 如果是基元类型或 Decimal、DateTime
                if (targetType != TypeCode.Empty &&
                    targetType != TypeCode.DBNull &&
                    targetType != TypeCode.Object)
                {
                    if (GetValueType(targetType, out var valueType))
                    {
                        property.Value.Type = valueType;
                    }
                }
            }

            static bool GetValueType(TypeCode targetType, out string? valueType)
            {
                valueType = null;
                switch (targetType)
                {
                    case TypeCode.Boolean: valueType = "boolean"; break;
                    case TypeCode.Char: valueType = "string"; break;
                    case TypeCode.SByte: valueType = "integer"; break;
                    case TypeCode.Byte: valueType = "integer"; break;
                    case TypeCode.Int16: valueType = "integer"; break;
                    case TypeCode.UInt16: valueType = "integer"; break;
                    case TypeCode.Int32: valueType = "integer"; break;
                    case TypeCode.UInt32: valueType = "integer"; break;
                    case TypeCode.Int64: valueType = "integer"; break;
                    case TypeCode.UInt64: valueType = "integer"; break;
                    case TypeCode.Single: valueType = "number"; break;
                    case TypeCode.Double: valueType = "number"; break;
                    case TypeCode.Decimal: valueType = "number"; break;
                    case TypeCode.DateTime: valueType = "string"; break;
                    case TypeCode.String: valueType = "string"; break;
                    // 一般不需要处理对象
                    // case TypeCode.Object: valueType = p.PropertyType.Name; break;
                    default: return false;
                }
                return true;
            }
        }
    }

一般不需要处理对象,如果有需要,可以使用:

case TypeCode.Object: property.Value.Type = p.PropertyType.Name;break;

然后配置 Swagger 服务。

            builder.Services.AddSwaggerGen(options =>
            {
                options.SchemaFilter<CustomSchemaFilter>();
            });

对应的基元类型在 Swagger 中显示的类型:

    public class Test
    {
        public Boolean Value1 { get; set; }
        public char Value2 { get; set; }
        public sbyte Value3 { get; set; }
        public byte Value4 { get; set; }
        public Int16 Value5 { get; set; }
        public UInt16 Value6 { get; set; }
        public Int32 Value7 { get; set; }
        public UInt32 Value8 { get; set; }
        public Int64 Value9 { get; set; }
        public UInt64 Value { get; set; }
        public Single Value10 { get; set; }
        public Double Value11 { get; set; }
        public Decimal Value12 { get; set; }
        public DateTime Value13 { get; set; }
        public String Value14 { get; set; }
    }
{
value1  boolean
value2  string
value3  integer($int32)
value4  integer($int32)
value5  integer($int32)
value6  integer($int32)
value7  integer($int32)
value8  integer($int32)
value9  integer($int64)
value   integer($int64)
value10 number($float)
value11 number($double)
value12 number($double)
value13 string($date-time)
value14 string
}

痴者工良

高级程序员劝退师

文章评论