如何将JSON.Net CamelCasePropertyNamesContractResolver与点分隔的名称一起使用?

时间:2019-01-22 12:10:27

标签: asp.net-mvc json.net camelcasing

我们的应用程序使用验证属性来利用ASP.NET模型验证,但是这为验证错误提供了点分隔的名称。当通过CamelCasePropertyNamesContractResolver传递时,这仅适用于第一个点之前的驼峰字母,而我们希望将驼峰字母应用于名称的每个部分。

例如,我们当前得到当前的json响应:

{
    "body.State": [
        "The state field is required."
    ],
    "body.LatestVersion": [
        "The latestVersion field is required."
    ]
}

但是渴望离开:

{
    "body.state": [
        "The state field is required."
    ],
    "body.latestVersion": [
        "The latestVersion field is required."
    ]
}

在我们的MVC设置中,确实有一条类似于

的行
services.AddJsonOptions(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());

我们希望能找到任何解决方案,无论是对设置解析器的方式还是对验证的修改方式。


编辑:仅供参考,生成该请求的请求的模型结构如下:

public sealed class RequestModel
{
    [FromRoute, DisplayName("entity"), Required, MaximumLength(255)]
    public string Entity { get; set; }

    [FromBody, DisplayName("body"), Required]
    public BodyModel Body { get; set; }
}

public sealed class BodyModel
{
    [DisplayName("latestVersion"), Required, MaximumLength(255)]
    public string LatestVersion { get; set; }

    [DisplayName("state"), Required]
    public ModelState State { get; set; }
}

,发送的请求正文为:

{
}

1 个答案:

答案 0 :(得分:1)

假设对于某些IDictionary<string, T>,验证错误已被序列化为T,那么对应于字典键的JSON属性名称可以分段驼峰式地封装在每个.之间通过创建自定义的naming strategy字符。

Json.NET封装了逻辑,以算法重新映射NamingStrategy类型(特别是CamelCaseNamingStrategy)中的属性名称和字典键(例如,驼峰大小写)。要修改命名策略的逻辑以应用于.个字符之间的属性名称的每个部分,您可以采用decorator pattern并创建一个装饰器命名策略,以将一些内部策略应用于该属性名称的每个部分。像这样的名字:

public class PiecewiseNamingStrategy : NamingStrategy
{
    readonly NamingStrategy baseStrategy;

    public PiecewiseNamingStrategy(NamingStrategy baseStrategy)
    {
        if (baseStrategy == null)
            throw new ArgumentNullException();
        this.baseStrategy = baseStrategy;
    }

    protected override string ResolvePropertyName(string name)
    {
        return String.Join(".", name.Split('.').Select(n => baseStrategy.GetPropertyName(n, false)));
    }
}

然后,按如下所示配置MVC:

options.ContractResolver = new DefaultContractResolver
{
    NamingStrategy = new PiecewiseNamingStrategy(new CamelCaseNamingStrategy()) 
    { 
        OverrideSpecifiedNames = true, ProcessDictionaryKeys = true 
    },
};

这利用了一个事实,如reference source所示,CamelCasePropertyNamesContractResolver基本上只是DefaultContractResolver的子类,它使用CamelCaseNamingStrategy与{{1} }和ProcessDictionaryKeys = true

注意: