.Net Core如何将[FromQuery]参数从驼峰/帕斯卡命名转为snake_case
提问内容
我尝试了.NET Core API设置snake_case JSON的相关方案,但该方案仅对请求/响应报文生效,无法作用于[FromQuery]绑定的参数。请问是否有方法可以强制将[FromQuery]参数的格式设置为snake_case?目前我已有的配置如下所示:
解决方案
你之前配置的JSON序列化规则仅作用于请求/响应体的JSON序列化流程,ASP.NET Core默认的Query参数绑定走独立的命名匹配逻辑,因此需要单独配置才可以实现全局snake_case格式的Query参数绑定。
方案1:单个参数/属性标记(适配少量场景)
如果仅少数接口需要适配snake_case参数,直接在参数或者参数类的属性上指定Name属性即可:
// 单个参数写法 public IActionResult GetUser([FromQuery(Name = "user_id")] int userId) { // 业务逻辑 } // 复杂参数类写法 public class PageQueryParams { [FromQuery(Name = "page_size")] public int PageSize { get; set; } [FromQuery(Name = "page_index")] public int PageIndex { get; set; } }
方案2:全局配置snake_case的Query参数绑定(无需逐个标记)
如果需要全项目统一适配snake_case的Query参数,按照以下步骤配置即可:
- 实现蛇形命名转换工具类
using System.Text.RegularExpressions; public static class StringExtensions { public static string ToSnakeCase(this string input) { if (string.IsNullOrEmpty(input)) return input; // 匹配开头的下划线保留,剩余部分驼峰转蛇形 var startUnderscores = Regex.Match(input, @"^_+"); return startUnderscores + Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToLower(); } }
注意:如果你的项目使用Newtonsoft.Json作为JSON序列化组件,可以直接复用其内置的
SnakeCaseNamingStrategy实现命名转换,无需自己写正则转换逻辑,兼容性更好:using Newtonsoft.Json.Serialization; public static class StringExtensions { private static readonly SnakeCaseNamingStrategy _snakeCaseNaming = new SnakeCaseNamingStrategy(); public static string ToSnakeCase(this string input) { return _snakeCaseNaming.GetPropertyName(input, false); } }
- 实现自定义Query值提供器工厂
using Microsoft.AspNetCore.Mvc.ModelBinding; public class SnakeCaseQueryValueProviderFactory : IValueProviderFactory { public Task CreateValueProviderAsync(ValueProviderFactoryContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); var queryCollection = context.ActionContext.HttpContext.Request.Query; if (queryCollection != null && queryCollection.Count > 0) { // 将所有Query参数的key转为蛇形后构造值提供器 var snakeCaseQueryDict = queryCollection.ToDictionary( kv => kv.Key.ToSnakeCase(), kv => kv.Value); var valueProvider = new DictionaryBasedValueProvider( BindingSource.Query, snakeCaseQueryDict, culture: null); context.ValueProviders.Add(valueProvider); } return Task.CompletedTask; } }
- 在Program.cs中注册该工厂,替换默认的Query值提供器
var builder = WebApplication.CreateBuilder(args); // 添加控制器服务 builder.Services.AddControllers(options => { // 移除默认的QueryString值提供器工厂 var defaultQueryFactory = options.ValueProviderFactories .OfType<QueryStringValueProviderFactory>() .FirstOrDefault(); if (defaultQueryFactory != null) { options.ValueProviderFactories.Remove(defaultQueryFactory); } // 添加自定义的蛇形命名Query值提供器工厂 options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); // 保留你原来的其他Mvc配置 }) // 保留你原来的JSON序列化配置 .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.SnakeCaseLower; }); // 其他服务注册... var app = builder.Build(); // 中间件配置... app.Run();
配置完成后,所有[FromQuery]绑定的参数都会自动适配snake_case格式的请求参数,无需额外标记属性。
内容的提问来源于stack exchange,提问作者Carlo Luisito
相关产品推荐
相关产品推荐

