c# - 更改单个 ASP.NET Core 控制器的 JSON 序列化设置
问题描述
我有两个控制器控制器:ControllerA
和ControllerB
. 每个控制器的基类是Controller
.
需要以ControllerA
默认格式(camelCase)返回 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 个控制器配置或注释此功能?
解决方案
ASP.NET Core 3.0+
您可以结合使用Action Filter和Output Formatter来实现这一点。
3.0+ 的情况看起来有些不同,其中 3.0+ 的默认 JSON 格式化程序基于System.Text.Json
. 在撰写本文时,它们没有对蛇形命名策略的内置支持。
但是,如果您使用 3.0+ 的 Json.NET(详细信息在docs中),则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));
}
}
}
ASP.NET 核心 2.x
您可以结合使用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
,代码在相应的操作之后运行,并首先检查结果是否为 an ObjectResult
(这也适用于OkObjectResult
由于继承)。如果它是一个ObjectResult
,过滤器只需添加一个自定义版本的 a JsonOutputFormatter
,它将使用 序列化属性SnakeCaseNamingStrategy
。构造函数中的第二个参数JsonOutputFormatter
是从 DI 容器中检索的。
要使用此过滤器,只需将其应用于相关控制器:
[SnakeCase]
public class ControllerB : Controller { }
注意:例如,您可能希望在某个地方提前创建JsonOutputFormatter
/ NewtonsoftJsonOutputFormatter
- 我在示例中没有走那么远,因为这是手头问题的次要问题。
推荐阅读
- symfony - 使用 ManyToOne 关系实体,我如何访问外键 ID?
- c# - 为什么当我更改参考 A 的值时,原始实例不会更改?
- php - 批准多个编辑的 Wordpress 帖子
- java - 可以搜索Response.getHits().getHits(); 抛出空指针异常
- selenium - 从 Web 浏览器访问应用程序保存的数据
- c# - hive jdbc 驱动程序:javax.xml.stream.XMLStreamException:尝试输出第二个根,
- load-balancing - 如何在 HAProxy 中使用 external-check 命令
- clojure - 使用 map 时收集顺序颠倒,但使用 mapv 很好
- php - Laravel 5.4:返回响应 json groupBy created_at
- node.js - npm npm run watch-poll 宅基地错误