扩展 CamelCasePropertyNamesContractResolver 不起作用

Extending CamelCasePropertyNamesContractResolver does not work

我扩展了 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 class) 的覆盖方法:

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() 方法从未被调用(使用断点对其进行了测试),因此似乎只有我父 class (CamelCasePropertyNamesContractResolver) 的 ResolvePropertyName() 方法以某种方式被调用。

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

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

ResolvePropertyName() is no longer called by CamelCasePropertyNamesContractResolver. This is documented in Issue #950: Breaking change in 9.0.1 for custom contract resolvers? which was resolved by JamesNK如下:

JamesNK commented on Jul 4, 2016

Yes that will now break. That method [ResolvePropertyName] is never called because of changes in how CamelCasePropertyNamesContractResolver works.

What you could do is inherit from CamelCaseNamingStrategy and do something similar, then assign that to DefaultContractResolver. Note that you should cache the contract resolver on a static variable so it isn't recreated all the time.

按照那里的建议,您应该像这样从 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;

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