![](/img/trans.png)
[英]Change System.Text.Json Serialization Options of a single ASP.NET Core API controller or single Action in ASP.NET Core 3
[英]Change the JSON serialization settings of a single ASP.NET Core controller
我有两个控制器控制器: ControllerA
和ControllerB
。 每个控制器的基类是Controller
。
ControllerA
需要以默认格式(驼峰式大小写)返回 JSON。 ControllerB
需要以不同的 JSON 格式返回数据:snake_case。
如何在 ASP.NET Core 3.x 和 2.1 中实现这一点?
我试过startup
:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new StringEnumConverter());
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
})
.AddControllersAsServices();
但这将改变所有控制器的序列化,而不仅仅是ControllerB
。 如何为 1 个控制器配置或注释此功能?
您可以使用Action Filter和Output Formatter的组合来实现这一点。
3.0+ 的情况看起来有点不同,3.0+ 的默认 JSON 格式器基于System.Text.Json
。 在撰写本文时,这些还没有对蛇形命名策略的内置支持。
但是,如果您将 Json.NET 与 3.0+( 文档中的详细信息)一起使用,则上面的SnakeCaseAttribute
仍然可行,但有一些更改:
JsonOutputFormatter
现在是NewtonsoftJsonOutputFormatter
。NewtonsoftJsonOutputFormatter
构造函数需要一个MvcOptions
参数。这是代码:
public class SnakeCaseAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext ctx)
{
if (ctx.Result is ObjectResult objectResult)
{
objectResult.Formatters.Add(new NewtonsoftJsonOutputFormatter(
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
},
ctx.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>(),
ctx.HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value));
}
}
}
您可以使用Action Filter和Output Formatter的组合来实现这一点。 以下是操作过滤器的外观示例:
public class SnakeCaseAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext ctx)
{
if (ctx.Result is ObjectResult objectResult)
{
objectResult.Formatters.Add(new JsonOutputFormatter(
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
},
ctx.HttpContext.RequestServices.GetRequiredService<ArrayPool<char>>()));
}
}
}
使用OnActionExecuted
,代码在相应的操作之后运行,并首先检查结果是否为ObjectResult
(由于继承,这也适用于OkObjectResult
)。 如果它是ObjectResult
,过滤器只需添加一个JsonOutputFormatter
的自定义版本,该版本将使用SnakeCaseNamingStrategy
序列化属性。 JsonOutputFormatter
构造函数中的第二个参数是从 DI 容器中检索的。
为了使用这个过滤器,只需将它应用到相关的控制器:
[SnakeCase]
public class ControllerB : Controller { }
注意:例如,您可能希望在某处提前创建JsonOutputFormatter
/ NewtonsoftJsonOutputFormatter
- 我在示例中没有走那么远,因为这是手头问题的次要问题。
最终创建了我在端点上使用的这个方法:
{
// needed to get the same date and property formatting
// as the Search Service:
var settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
},
DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ"
};
return Json(result, settings);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.