FromQuery 参数从 camelCase/PascalCase 到 snake_case .Net Core
FromQuery parameters from camelCase/PascalCase to snake_case .Net Core
我在这里尝试了解决方案: 但似乎这仅适用于 request/response 有效负载。有没有办法在我的 [FromQuery] 参数上强制使用 snake_case 格式?
目前这是我目前拥有的
您所做的是 json 核心中的 json 序列化,但您想要的是更改 Swagger UI。它们是完全不同的东西。
第一种方式,可以添加如下属性:[FromQuery(Name = "account_number")]
.
或者你可以自定义一个属性来避免写成snake_case:
public class CustomFromQueryAttribute : FromQueryAttribute
{
public CustomFromQueryAttribute(string name)
{
Name = name.ToSnakeCase();
}
}
自定义 ToSnakeCase
用于字符串扩展:
public static class StringExtensions
{
public static string ToSnakeCase(this string o) =>
Regex.Replace(o, @"(\w)([A-Z])", "_").ToLower();
}
用法:
public voidGet([CustomFromQuery("AccountNumber")]string AccountNumber)
注:
实际上这种方式等于使用public voidGet(string account_number)
,所以Swagger UI改变了。
第二种方式,你可以像下面这样自定义IOperationFilter
来改变Swagger UI:
public class SnakecasingParameOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null) operation.Parameters = new List<OpenApiParameter>();
else {
foreach(var item in operation.Parameters)
{
item.Name = item.Name.ToSnakeCase();
}
}
}
}
像下面这样注册服务:
services.AddSwaggerGen(c =>
{
c.OperationFilter<SnakecasingParameOperationFilter>();
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi5_0", Version = "v1" });
});
但是这种方式将请求查询字符串更改为蛇形,其中有一个额外的_
,它与后端参数不匹配。因此,您还需要自定义值提供程序来查找蛇形查询参数:
SnakeCaseQueryValueProvider:
public class SnakeCaseQueryValueProvider : QueryStringValueProvider, IValueProvider
{
public SnakeCaseQueryValueProvider(
BindingSource bindingSource,
IQueryCollection values,
CultureInfo culture)
: base(bindingSource, values, culture)
{
}
public override bool ContainsPrefix(string prefix)
{
return base.ContainsPrefix(prefix.ToSnakeCase());
}
public override ValueProviderResult GetValue(string key)
{
return base.GetValue(key.ToSnakeCase());
}
}
我们还必须为我们的值提供者实现一个工厂:
public class SnakeCaseQueryValueProviderFactory : IValueProviderFactory
{
public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var valueProvider = new SnakeCaseQueryValueProvider(
BindingSource.Query,
context.ActionContext.HttpContext.Request.Query,
CultureInfo.CurrentCulture);
context.ValueProviders.Add(valueProvider);
return Task.CompletedTask;
}
}
注册服务:
services.AddControllers(options =>
{
options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //add this...
}).AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
});
我在这里尝试了解决方案:
目前这是我目前拥有的
您所做的是 json 核心中的 json 序列化,但您想要的是更改 Swagger UI。它们是完全不同的东西。
第一种方式,可以添加如下属性:[FromQuery(Name = "account_number")]
.
或者你可以自定义一个属性来避免写成snake_case:
public class CustomFromQueryAttribute : FromQueryAttribute
{
public CustomFromQueryAttribute(string name)
{
Name = name.ToSnakeCase();
}
}
自定义 ToSnakeCase
用于字符串扩展:
public static class StringExtensions
{
public static string ToSnakeCase(this string o) =>
Regex.Replace(o, @"(\w)([A-Z])", "_").ToLower();
}
用法:
public voidGet([CustomFromQuery("AccountNumber")]string AccountNumber)
注:
实际上这种方式等于使用public voidGet(string account_number)
,所以Swagger UI改变了。
第二种方式,你可以像下面这样自定义IOperationFilter
来改变Swagger UI:
public class SnakecasingParameOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null) operation.Parameters = new List<OpenApiParameter>();
else {
foreach(var item in operation.Parameters)
{
item.Name = item.Name.ToSnakeCase();
}
}
}
}
像下面这样注册服务:
services.AddSwaggerGen(c =>
{
c.OperationFilter<SnakecasingParameOperationFilter>();
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi5_0", Version = "v1" });
});
但是这种方式将请求查询字符串更改为蛇形,其中有一个额外的_
,它与后端参数不匹配。因此,您还需要自定义值提供程序来查找蛇形查询参数:
SnakeCaseQueryValueProvider:
public class SnakeCaseQueryValueProvider : QueryStringValueProvider, IValueProvider
{
public SnakeCaseQueryValueProvider(
BindingSource bindingSource,
IQueryCollection values,
CultureInfo culture)
: base(bindingSource, values, culture)
{
}
public override bool ContainsPrefix(string prefix)
{
return base.ContainsPrefix(prefix.ToSnakeCase());
}
public override ValueProviderResult GetValue(string key)
{
return base.GetValue(key.ToSnakeCase());
}
}
我们还必须为我们的值提供者实现一个工厂:
public class SnakeCaseQueryValueProviderFactory : IValueProviderFactory
{
public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var valueProvider = new SnakeCaseQueryValueProvider(
BindingSource.Query,
context.ActionContext.HttpContext.Request.Query,
CultureInfo.CurrentCulture);
context.ValueProviders.Add(valueProvider);
return Task.CompletedTask;
}
}
注册服务:
services.AddControllers(options =>
{
options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //add this...
}).AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
});