客户要求ASP.NET Core API返回特定格式,怎么办?

当ASP.NET Core API提供给到外部系统使用时,在某些情况下,可能需要根据这些外部系统的要求来格式化数据。

比如,客户就要求API的返回值属性名必须是PascalCase(如UserName),但是这些API需要同时提供给内部系统使用,默认都是CamelCase(如userName)。

怎么办?

虽然可以为外部系统重新做一套API,但是代价太大!能不能从自定义API的返回值上想办法?

在微软官方文档上找到一篇设置 ASP.NET Core Web API 中响应数据的格式[1],介绍了响应格式 URL 映射。

使用FormatFilter可以根据请求路径的路由映射将相应映射到相应的格式上。

希望达到的效果:

[ApiController]
[Route("[controller]")]
[FormatFilter]
public class WeatherForecastController : ControllerBase
{
    [HttpGet("{format?}")]
    public IEnumerable<WeatherForecast> Get()

路由响应格式
WeatherForecast默认格式CamelCase
WeatherForecast?format=json2PascalCase

代码实现

首先,需要让API支持自定义格式,返回MediaType还是application/json

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.FormatterMappings.SetMediaTypeMappingForFormat
            ("json2", MediaTypeHeaderValue.Parse("application/json"));
    });
}

接着,我们需要替换掉默认的Json OutputFomatter:

for (int i = 0; i < options.OutputFormatters.Count; i++)
{
    if (options.OutputFormatters[i] is Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter jsonOutputFormatter)
    {
        options.OutputFormatters[i] = new CustomJsonOutputFormatter(jsonOutputFormatter.SerializerOptions);
        break;
    }
} 

CustomJsonOutputFormatter的代码如下:

public class CustomJsonOutputFormatter : SystemTextJsonOutputFormatter
{
    private readonly SystemTextJsonOutputFormatter pascalCaseFormater;
    public CustomJsonOutputFormatter(JsonSerializerOptions jsonSerializerOptions) : base(jsonSerializerOptions)
    {
        var newOptions = new JsonSerializerOptions(jsonSerializerOptions);
        newOptions.PropertyNamingPolicy = null;
        pascalCaseFormater = new SystemTextJsonOutputFormatter(newOptions);
    }

    public override Task WriteAsync(OutputFormatterWriteContext context)
    {
        if (GetFormat(context) == "json2")
        {
            return pascalCaseFormater.WriteAsync(context);
        }
        return base.WriteAsync(context);
    }

    private string? GetFormat(OutputFormatterWriteContext context)
    {
        if (context.HttpContext.Request.RouteValues.TryGetValue("format", out var obj))
        {
            var routeValue = Convert.ToString(obj, CultureInfo.InvariantCulture);
            return string.IsNullOrEmpty(routeValue) ? null : routeValue;
        }

        var query = context.HttpContext.Request.Query["format"];
        if (query.Count > 0)
        {
            return query.ToString();
        }

        return "json";
    }
}

如果format是json2,就用pascalCaseFormater处理,否则使用默认处理。

小插曲: 需要设置pascalCaseFormater的JsonSerializerOptions.PropertyNamingPolicy属性,指定用于将对象的属性名称转换为其他格式(例如PascalCase)的策略,本来还准备实现一个PascalCasePolicy但是转念一想,C#本身的Property名不就是PascalCase的吗?!直接将PropertyNamingPolicy设为null不处理就行了。

结论

最后,运行结果如下: 

完全满足了要求,只需要客户在每个API请求URL上加上?format=json2即可。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

参考资料

[1]

设置 ASP.NET Core Web API 中响应数据的格式: https://docs.microsoft.com/zh-cn/aspnet/core/web-api/advanced/formatting?view=aspnetcore-5.0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值