C# 如何在JSON模型类中使用保留关键字作为标识符?

C# 如何在JSON模型类中使用保留关键字作为标识符?,c#,.net,asp.net-mvc,asp.net-web-api,C#,.net,Asp.net Mvc,Asp.net Web Api,我以前从未使用过Web API,但我需要一个能够接受/返回JSON对象的Web服务,使用它似乎是合理的。它看起来非常简单(如果不是出于我的目的有点过分),但是我需要处理的数据结构看起来像: { "values":["foo", "bar"], "default":"bar" } 于是我制作了一个模型对象: class DropDownValues { public string[] values { get; set; } public string defau

我以前从未使用过Web API,但我需要一个能够接受/返回JSON对象的Web服务,使用它似乎是合理的。它看起来非常简单(如果不是出于我的目的有点过分),但是我需要处理的数据结构看起来像:

{
    "values":["foo", "bar"],
    "default":"bar"
}
于是我制作了一个模型对象:

class DropDownValues {
    public string[] values { get; set; }
    public string default { get; set; }
}

问题是默认值似乎是一个受保护的关键字。一定有办法解决这个问题,对吧?

你可以在C中的关键字前面加上@作为标识符。

下拉值使用驼峰约定:

class DropDownValues {
    public string[] values { get; set; }
    public string default { get; set; }
}
您可以使用前缀
@
进行传递,但它仍然不遵循C#编码约定

更好的解决方案是使用
CamelCasePropertyNamesContractResolver
,既可以避免保留关键字,又可以使用C#编码约定:

class DropDownValues {
    public string[] Values { get; set; }
    public string Default { get; set; }
}
并自定义
JsonFormatter
,以避免C#和json对象之间的约定不匹配,如下所示:

var jsonFormatter = configuration.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings = new JsonSerializerSettings()
{  
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

我建议走不同的路。尽可能保持C#对象模型的标准(我不会使用
@
符号和
C#关键字作为属性名称)

我们可以分离序列化(JSON)世界和C#对象——只需使用JSON.NET特性

使用最简单的方法之一是带有属性的装饰:

[JsonProperty(PropertyName = "default")]
public string DefaultValue { get; set; }
在这种情况下,我们必须在项目中引用Newtonsoft.Json。如果必须是POCO,我们可以引入从
DefaultContractResolver
派生的
CustomResolver
并在那里定义这些转换

但我想说,在这种情况下,关注点的分离是一种更纯粹的解决方案

编辑:JSON合同解析器草案(见注释)

重要提示:是Web API的一部分。它不仅是一个开放源代码,甚至微软团队也将其作为一个核心JSON序列化程序

1) 解决方案中已经安装了Newtonsoft.Json(作为Web.API的一部分)。因此,您不必单独下载(nuget)。它将始终位于您的
文件夹中。因此,使用属性只是添加引用。就在那里

2) 关于如何在保持POCO的同时执行属性填充,还有一个小草稿。正如我在这里试图解释的那样:,为了保持POCO(例如,我们确实从数据层上带有NHibernate的分层体系结构中获益),我们可以用
契约解析器
替换属性。我们的POCO库不需要引用任何内容

我们只需扩展服务层:

public class MyResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(
         MemberInfo member,
         MemberSerialization memberSerialization)
    {

        var jProperty = base.CreateProperty(member, memberSerialization);

        var propertyInfo = member as PropertyInfo;
        if (propertyInfo == null)
        {
            return jProperty;
        }

        // just adjust in case if Property name is DefaultValue
        var isDefaultValueProeprty =
                  propertyInfo.Name.Equals("DefaultValue");

        if(isDefaultValueProeprty)
        {
            jProperty.PropertyName = "default";
        }

        return jProperty;
    }
    ...
通过这种方式,我们向serailizer提供了与
[JsonPropertyAttribute]
相同的信息

现在,我们只需要使用它。有很多方法(例如,全局),但我们只能为控制器这样做:

protected override void Initialize(HttpControllerContext context)
{
  base.Initialize(context);

  var jSettings = context.Configuration.Formatters.JsonFormatter.SerializerSettings;
  jSettings.ContractResolver = MyResolver;
}

也许可以试试这个
publicstringselected{get;set;}
我确实喜欢这个解决方案,但不幸的是,我不能使用Newtonsoft(至少不需要经历很多麻烦)。您能详细介绍一下如何使用CustomResolver吗?