如何使用带有点分隔名称的 JSON.Net CamelCasePropertyNamesContractResolver?

How to use JSON.Net CamelCasePropertyNamesContractResolver with dot separated names?

我们的应用程序使用验证属性来使用 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; }
}

发送的请求正文是:

{
}

假设验证错误被序列化为某种IDictionary<string, T> for some T,那么字典键对应的JSON 属性名称可以分段通过创建自定义 naming strategy.

,在每个 . 字符之间使用驼峰式大小写

Json.NET 封装了在 NamingStrategy type, specifically CamelCaseNamingStrategy. To modify the logic of a naming strategy to apply to each portion of a property name between . characters, you can adopt the 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 的一个子类,它使用 CamelCaseNamingStrategyProcessDictionaryKeys = trueOverrideSpecifiedNames = true.

备注:

  • Json.NET 9.0.1 中引入了命名策略,因此此答案不适用于早期版本。

  • 您可能想要 .

  • 通过将NamingStrategy.ProcessDictionaryKeys设置为true,命名策略将应用于所有字典键。