内容目录
Model Class:
public class Test
{
[JsonConverter(typeof(string))]
public int Value { get; set; }
}
API Interface:
[HttpPost("aaa")]
public string AAA([FromBody] Test test)
{
return "11111111111";
}
However, Swagger still displays the type as int and does not reflect the JSON configuration.
Therefore, we need to configure Swagger to properly display the converted type information.
Define a filter:
/// <summary>
/// Swagger Model Class Filter
/// </summary>
public class MaomiSwaggerSchemaFilter : ISchemaFilter
{
/// <summary>
///
/// </summary>
/// <param name="schema">Properties in Swagger</param>
/// <param name="context">Model Class Context</param>
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
// Model class type
var type = context.Type;
// If the API parameter is not an object
if (type.IsPrimitive || TypeInfo.GetTypeCode(type) != TypeCode.Object)
{
return;
}
// If the API parameter is an object type
// Get all properties of the type
PropertyInfo[] ps = context.Type.GetProperties();
// Get all properties displayed in the Swagger file
// Note that the documented properties have already been generated. Here we convert them late and replace them with the types to be displayed
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);
// If it is a primitive type, Decimal, or 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;
// Generally no need to handle objects
// case TypeCode.Object: valueType = p.PropertyType.Name; break;
default: return false;
}
return true;
}
}
}
Generally, there's no need to handle objects, but if necessary, you can use:
case TypeCode.Object: property.Value.Type = p.PropertyType.Name; break;
Then configure the Swagger service.
builder.Services.AddSwaggerGen(options =>
{
options.SchemaFilter<CustomSchemaFilter>();
});
Corresponding primitive types displayed in 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
}
文章评论