.NET 7 Web API如何根据请求动态配置JsonSerializerOptions
动态控制.NET 7 Web API JSON序列化行为
问题背景
我有一个返回User对象的.NET 7 Web API接口,User类定义如下:
public class User { public Guid? Id { get; set; } public String? Name { get; set; } public Int32? Age { get; set; } public String? HairColor { get; set; } }
当请求携带Select查询参数(例如值为Name)时,数据库仅返回Name属性,但接口通过Ok(users)返回的JSON会包含所有null或默认值的属性。为节省响应包体积,希望此时仅返回非默认值的属性;若请求未携带Select查询参数,则返回所有属性(即使为null或默认值)。
需要动态设置JsonSerializerOptions:
JsonSerializerOptions options = new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault };
使得存在Select参数时序列化忽略null/default属性,否则返回所有属性。
解决方案
方法一:单个Action内直接控制序列化选项
在API的Action方法中,先获取Select查询参数,根据参数是否存在选择对应的序列化配置,返回自定义JsonResult:
[HttpGet] public IActionResult GetUsers([FromQuery] string? select) { // 模拟数据库查询:根据select参数返回仅包含指定属性的User集合 var users = FetchUsersFromDatabase(select); var serializerOptions = string.IsNullOrEmpty(select) ? new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.Never } : new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; return new JsonResult(users, serializerOptions); }
这种方式简单直接,适合仅单个Action需要该逻辑的场景。
方法二:全局ActionFilter统一控制
如果多个Action都需要此逻辑,可以自定义过滤器,在结果执行阶段动态修改序列化配置:
public class DynamicJsonFilter : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext context) { if (context.Result is ObjectResult objectResult) { var selectParam = context.HttpContext.Request.Query["select"].FirstOrDefault(); JsonSerializerOptions options; if (!string.IsNullOrEmpty(selectParam)) { options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; } else { options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.Never }; } // 替换ObjectResult的序列化选项 objectResult.JsonSerializerOptions = options; } base.OnResultExecuting(context); } }
注册全局过滤器(Program.cs):
builder.Services.AddControllers(options => { options.Filters.Add<DynamicJsonFilter>(); });
或单独在Action上启用:
[HttpGet] [DynamicJsonFilter] public IActionResult GetUsers([FromQuery] string? select) { var users = FetchUsersFromDatabase(select); return Ok(users); }
这种方式可统一管理多个Action的序列化逻辑,减少重复代码。
注意事项
若项目已有全局JsonSerializerOptions配置,可基于全局配置修改,避免重复设置其他属性:
var globalOptions = context.HttpContext.RequestServices.GetRequiredService<IOptions<JsonOptions>>().Value.JsonSerializerOptions; var options = new JsonSerializerOptions(globalOptions); options.DefaultIgnoreCondition = string.IsNullOrEmpty(selectParam) ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingDefault;
内容的提问来源于stack exchange,提问作者ScubaSteve
相关产品推荐
相关产品推荐

