前言
上次,我们用
客户就要求API的返回值属性名必须是PascalCase(如UserName),但是这些API需要同时提供给内部系统使用,默认都是CamelCase(如userName)。
其实,返回的都是JSON格式,只是写入属性名的大小写不一样。
那么,直接修改JSON格式化实现,应该也是可行的?!
问题
在ASP.NET Core 3.0或更高版本中,默认JSON格式化程序基于 System.Text.Json
,可以配置Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions实现自定义功能。
比如,设置返回值属性名是PascalCase格式:
public void ConfigureServices(IServiceCollection services)
{services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
}
但是,这种只能实现固定设置,不能满足不同请求返回不同格式的需求。
这时,我们可以利用Newtonsoft.Json
实现更灵活的配置。
添加Newtonsoft.Json支持
引用nuget包Microsoft.AspNetCore.Mvc.NewtonsoftJson
,并修改Startup.cs,代码如下:
public void ConfigureServices(IServiceCollection services)
{...services.AddControllers().AddNewtonsoftJson(options =>{options.SerializerSettings.ContractResolver = new MyCustomContractResolver();});
}
使用自定义类MyCustomContractResolver
格式化JSON。
MyCustomContractResolver实现
MyCustomContractResolver
实现代码如下:
public class MyCustomContractResolver : DefaultContractResolver {private CamelCaseNamingStrategy _camelCase = new CamelCaseNamingStrategy();public override JsonContract ResolveContract(Type type){return CreateContract(type);}protected override string ResolvePropertyName(string propertyName){if (GetFormat() == "json2"){return propertyName;}return _camelCase.GetPropertyName(propertyName, false);}private string GetFormat(){Microsoft.Extensions.Primitives.StringValues headerValues;if (AppContext.Current.Request.Headers.TryGetValue("x-format", out headerValues)){return headerValues.FirstOrDefault();}return "json";}
}
默认的
ResolveContract
缓存了指定类型的格式化设置,以加快运行速度,不能满足不同请求对同一类型执行不同的格式化要求。因此,为演示方便,这里去掉了缓存,你也可以实现自定义缓存GetFormat
是判断当前请求格式化方式的自定义方法。为演示方便,这里判断的是x-format
Header,你也可以改成其他方式,比如根据当前用户凭证进行判断AppContext.Current
是对当前请求的HttpContext的封装
结论
最后,分别发送请求,运行效果如下图:
使用x-format
Header
不使用x-format
Header
完全满足了要求,只需要客户在每个API请求加上x-format
Header即可。
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!