【问题标题】:Extending CamelCasePropertyNamesContractResolver does not work扩展 CamelCasePropertyNamesContractResolver 不起作用
【发布时间】:2019-03-21 21:35:10
【问题描述】:

我扩展了 Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver 并在我的 WebApi 中应用新的解析器:

public static void Register(HttpConfiguration config)
{
    var json = config.Formatters.JsonFormatter.SerializerSettings;
    json.ContractResolver = new CustomPropertyNamesContractResolver();
    json.Formatting = Formatting.Indented;

    config.MapHttpAttributeRoutes();
}

这是我的自定义名称解析器(CustomPropertyNamesContractResolver 类)的重写方法:

protected override string ResolvePropertyName(string propertyName)
{
    if (propertyName.Equals("ID"))
        return "id";

    // return the camelCase
    propertyName = base.ResolvePropertyName(propertyName);

    if (propertyName.EndsWith("ID"))
        propertyName = propertyName.Substring(0, propertyName.Length - 1) + "d";
    return propertyName;
}

我的问题是结果确实是驼峰式的,但是像“QuestionID”这样的属性永远不会转换为“questionId”——我一直收到的是“questionID”。

另外,我的自定义 ResolvePropertyName() 方法永远不会被调用(用断点测试它),所以似乎只有我的父类 (CamelCasePropertyNamesContractResolver) 的 ResolvePropertyName() 方法被以某种方式调用。

现在,当我直接从 DefaultContractResolver(CamelCasePropertyNamesContractResolver 的父级)继承时,我的自定义 ResolvePropertyName() 方法被调用。

谁能解释一下这里发生了什么? 我错过了什么吗?

【问题讨论】:

  • 这种行为的原因是 CamelCasePropertyNamesContractResolver.ResolvePropertyName() 的签名,如下所示?受保护的内部覆盖字符串 ResolvePropertyName(string propertyName)

标签: c# json json.net asp.net-web-api2 camelcasing


【解决方案1】:

ResolvePropertyName() 不再由CamelCasePropertyNamesContractResolver 调用。这在Issue #950: Breaking change in 9.0.1 for custom contract resolvers? 中记录在resolved JamesNK 中,如下所示:

JamesNK 于 2016 年 7 月 4 日发表评论

是的,现在会中断。由于 CamelCasePropertyNamesContractResolver 的工作方式发生了变化,因此永远不会调用该方法 [ResolvePropertyName]。

您可以做的是从 CamelCaseNamingStrategy 继承并执行类似的操作,然后将其分配给 DefaultContractResolver。请注意,您应该将合约解析器缓存在一个静态变量上,这样它就不会一直重新创建。

按照那里的建议,您应该像这样从 CamelCaseNamingStrategy 继承:

public class CustomNamingStrategy : CamelCaseNamingStrategy
{
    protected override string ResolvePropertyName(string propertyName)
    {
        if (propertyName.Equals("ID"))
            return "id";

        // return the camelCase
        propertyName = base.ResolvePropertyName(propertyName);

        if (propertyName.EndsWith("ID"))
            propertyName = propertyName.Substring(0, propertyName.Length - 1) + "d";
        return propertyName;
    }
}

然后将其设置为DefaultContractResolver.NamingStrategy,如下所示:

json.ContractResolver = new DefaultContractResolver { NamingStrategy = new CustomNamingStrategy() };

或者,由于我相信 ASP.NET Web API 使用它自己的合约解析器JsonContractResolver,您可能想要修改现有config.Formatters.JsonFormatter.SerializerSettings.ContractResolverNamingStrategy,假设已经在设置中分配了解析器:

var resolver = json.ContractResolver as DefaultContractResolver ?? new DefaultContractResolver();
resolver.NamingStrategy = new CustomNamingStrategy();
json.ContractResolver  = resolver;

(注意 - 我自己没有使用预先存在的解析器进行测试。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-30
    • 2014-02-20
    • 2011-08-18
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多