【问题标题】:How to use JSON.Net CamelCasePropertyNamesContractResolver with dot separated names?如何使用带有点分隔名称的 JSON.Net CamelCasePropertyNamesContractResolver?
【发布时间】:2019-01-22 12:10:26
【问题描述】:

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

并且正在发送的请求正文是:

{
}

【问题讨论】:

  • JSON 与您的模型完全不匹配,RequestModelBodyModel 都不会生成问题中显示的 当前 json 响应。您是否使用从this answerCan I specify a path in an attribute to map a property in my class to a child property in my JSON?JsonPathConverter 之类的东西?
  • 您是否认为这是验证生成的自动响应?我知道仅使用 JSON.Net 对其进行序列化不会产生响应,但我们是从内置的模型验证系统中获得的。我们在系统中的任何地方都没有 JsonPathConverter。
  • 在这种情况下,我不确定在序列化之前自动响应的 c# 数据模型是什么。但如果是Dictionary<string, List<string>>,那么我可以告诉你怎么做。
  • 它确实在引擎盖下表示为某种形式的字典,是的。我相信它是一个ModelStateDictionary,它是一个stringModelStateEntry,它似乎在其中的某处保存了一个验证错误列表。
  • @dbc 你能详细说明一下字典的解决方案吗?

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


【解决方案1】:

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

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 的子类,它使用CamelCaseNamingStrategyProcessDictionaryKeys = trueOverrideSpecifiedNames = true

注意事项:

【讨论】:

  • 这完全符合要求。我们将评估是否要实施它(因为它确实适用于所有字典),但非常感谢您的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多