【问题标题】:Set JSON CamelCase per Web API request为每个 Web API 请求设置 JSON CamelCase
【发布时间】:2015-11-02 08:39:44
【问题描述】:

Web API 使用 Json.Net 格式化程序来序列化其 JSON 响应,这使您可以在启动时为整个应用程序轻松自定义生成的 JSON 格式:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

这允许您解决 C# 语法偏好 PascalCase 和基于 javascript 的客户端偏好 camelCase 之间的问题。但是,在不考虑客户端请求实际来自谁的情况下,在 API 上全局设置它似乎假设 API 将只有一种类型的客户端,而您为 API 设置的任何内容都是它必须的方式。

我的 API 有多种客户端类型(javascript、iOS、Android、C#),我正在寻找一种方法来设置 Json.Net SerializerSettings per request,以便客户端可以请求他们的通过某种方式(可能是自定义标头或 queryString 参数)来覆盖默认值的首选格式。

在 Web API 中设置每个请求的 Json.Net SerializerSettings 的最佳方法是什么?

【问题讨论】:

    标签: asp.net-web-api json.net


    【解决方案1】:

    在 Rick Strahl 的 blog post 关于创建 JSONP 媒体类型格式化程序的一些帮助下,我提出了一个解决方案,允许 API 根据客户端请求从 camelCase 动态切换到 PascalCase。

    创建一个派生自默认 JsonMediaTypeFormatter 并覆盖 GetPerRequestFormatterInstance 方法的 MediaTypeFormatter。您可以在此处实现您的逻辑以根据请求设置序列化程序设置。

    public class JsonPropertyCaseFormatter : JsonMediaTypeFormatter
    {
        private readonly JsonSerializerSettings globalSerializerSettings;
    
        public JsonPropertyCaseFormatter(JsonSerializerSettings globalSerializerSettings)
        {
            this.globalSerializerSettings = globalSerializerSettings;
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
        }
    
        public override MediaTypeFormatter GetPerRequestFormatterInstance(
            Type type,
            HttpRequestMessage request,
            MediaTypeHeaderValue mediaType)
        {
            var formatter = new JsonMediaTypeFormatter
            {
                SerializerSettings = globalSerializerSettings
            };
    
            IEnumerable<string> values;
    
            var result = request.Headers.TryGetValues("X-JsonResponseCase", out values)
                ? values.First()
                : "Pascal";
    
            formatter.SerializerSettings.ContractResolver = 
                result.Equals("Camel", StringComparison.InvariantCultureIgnoreCase)
                    ? new CamelCasePropertyNamesContractResolver()
                    : new DefaultContractResolver();
    
            return formatter;
        }
    }
    

    请注意,我将 JsonSerializerSettings 参数作为构造函数参数,以便我们可以继续使用 WebApiConfig 来设置我们想要使用的任何其他 json 设置,并让它们仍然应用在这里。

    然后在您的 WebApiConfig 中注册此格式化程序:

    config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
    config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
    
    config.Formatters.Insert(0,
        new JsonPropertyCaseFormatter(config.Formatters.JsonFormatter.SerializerSettings));
    

    现在,标头值为 X-JsonResponseCase: Camel 的请求将在响应中收到驼峰式属性名称。显然,您可以更改该逻辑以使用您喜欢的任何标题或查询字符串参数。

    【讨论】:

    • 不错!我正在尝试这种方法。但我认为有一个问题:所有JsonMediaTypeFormatters 共享同一个SerializerSettings 对象。因此,当 ContractResolver 更改时,它也会更改 globalSerializerSettings 上的 ContractResolver
    • 是的,但它应该为每个进入指定 ContractResolver 的请求更改它
    • 谢谢,这正是我想要的!
    猜你喜欢
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 2018-06-29
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    相关资源
    最近更新 更多