[英]Change the JSON serialization settings of a single ASP.NET Core controller
I'm having two controller controllers: ControllerA
and ControllerB
.我有两个控制器控制器:
ControllerA
和ControllerB
。 The base class of each controller is Controller
.每个控制器的基类是
Controller
。
The ControllerA
needs to return JSON in the default format (camelCase). ControllerA
需要以默认格式(驼峰式大小写)返回 JSON。 The ControllerB
needs to return data in a different JSON format: snake_case. ControllerB
需要以不同的 JSON 格式返回数据:snake_case。
How can I implement this in ASP.NET Core 3.x and 2.1?如何在 ASP.NET Core 3.x 和 2.1 中实现这一点?
I've tried the startup
with:我试过
startup
:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new StringEnumConverter());
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
})
.AddControllersAsServices();
But this will change the serialization for all controllers, not just for ControllerB
.但这将改变所有控制器的序列化,而不仅仅是
ControllerB
。 How can I configure or annotate this feature for 1 controller?如何为 1 个控制器配置或注释此功能?
You can achieve this with a combination of an Action Filter and an Output Formatter .您可以使用Action Filter和Output Formatter的组合来实现这一点。
Things look a little different for 3.0+, where the default JSON-formatters for 3.0+ are based on System.Text.Json
. 3.0+ 的情况看起来有点不同,3.0+ 的默认 JSON 格式器基于
System.Text.Json
。 At the time of writing, these don't have built-in support for a snake-case naming strategy .在撰写本文时,这些还没有对蛇形命名策略的内置支持。
However, if you're using Json.NET with 3.0+ (details in the docs ), the SnakeCaseAttribute
from above is still viable, with a couple of changes:但是,如果您将 Json.NET 与 3.0+( 文档中的详细信息)一起使用,则上面的
SnakeCaseAttribute
仍然可行,但有一些更改:
JsonOutputFormatter
is now NewtonsoftJsonOutputFormatter
. JsonOutputFormatter
现在是NewtonsoftJsonOutputFormatter
。NewtonsoftJsonOutputFormatter
constructor requires an argument of MvcOptions
. NewtonsoftJsonOutputFormatter
构造函数需要一个MvcOptions
参数。 Here's the code:这是代码:
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));
}
}
}
You can achieve this with a combination of an Action Filter and an Output Formatter .您可以使用Action Filter和Output Formatter的组合来实现这一点。 Here's an example of what the Action Filter might look like:
以下是操作过滤器的外观示例:
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>>()));
}
}
}
Using OnActionExecuted
, the code runs after the corresponding action and first checks to see if the result is an ObjectResult
(which also applies to OkObjectResult
thanks to inheritance).使用
OnActionExecuted
,代码在相应的操作之后运行,并首先检查结果是否为ObjectResult
(由于继承,这也适用于OkObjectResult
)。 If it is an ObjectResult
, the filter simply adds a customised version of a JsonOutputFormatter
that will serialise the properties using SnakeCaseNamingStrategy
.如果它是
ObjectResult
,过滤器只需添加一个JsonOutputFormatter
的自定义版本,该版本将使用SnakeCaseNamingStrategy
序列化属性。 The second parameter in the JsonOutputFormatter
constructor is retrieved from the DI container. JsonOutputFormatter
构造函数中的第二个参数是从 DI 容器中检索的。
In order to use this filter, just apply it to the relevant controller:为了使用这个过滤器,只需将它应用到相关的控制器:
[SnakeCase]
public class ControllerB : Controller { }
Note: You might want to create the JsonOutputFormatter
/ NewtonsoftJsonOutputFormatter
ahead of time somewhere, for example - I've not gone that far in the example as that's secondary to the question at hand.注意:例如,您可能希望在某处提前创建
JsonOutputFormatter
/ NewtonsoftJsonOutputFormatter
- 我在示例中没有走那么远,因为这是手头问题的次要问题。
Ended up creating this method that I use on my end points:最终创建了我在端点上使用的这个方法:
{
// 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.