繁体   English   中英

更改单个 ASP.NET Core 控制器的 JSON 序列化设置

[英]Change the JSON serialization settings of a single ASP.NET Core controller

我有两个控制器控制器: ControllerAControllerB 每个控制器的基类是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 个控制器配置或注释此功能?

ASP.NET 核心 3.0+

您可以使用Action FilterOutput Formatter的组合来实现这一点。

3.0+ 的情况看起来有点不同,3.0+ 的默认 JSON 格式器基于System.Text.Json 在撰写本文时,这些还没有对蛇形命名策略的内置支持

但是,如果您将 Json.NET 与 3.0+( 文档中的详细信息)一起使用,则上面的SnakeCaseAttribute仍然可行,但有一些更改:

  1. JsonOutputFormatter现在是NewtonsoftJsonOutputFormatter
  2. 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 FilterOutput 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM