10

我以前从未使用过 Web API,但我需要一个可以接受/返回 JSON 对象的 Web 服务,并且使用它似乎是一件合理的事情。它看起来很简单(如果不是为了我的目的有点矫枉过正),但我需要处理的数据结构看起来像:

{
    "values":["foo", "bar"],
    "default":"bar"
}

所以我去制作一个模型对象:

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

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

4

3 回答 3

17

You can use keywords in C# as identifiers by prepending @ in front of them.

于 2013-05-23T02:35:10.453 回答
13

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

我们可以分离序列化 (JSON) 世界和 C# 对象 - 只需使用 Json.NET 功能。

最简单的使用方法之一是使用 Attribute 进行装饰:

[JsonProperty(PropertyName = "default")]
public string DefaultValue { get; set; }

在这种情况下,我们必须在项目中引用 Newtonsoft.Json。如果一定是POCO,我们可以在里面引入CustomResolverderrived fromDefaultContractResolver并定义这些转换...

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

编辑:JSON 合同解析器草案 (见评论)

重要提示:Newtonsoft.Json是 Web API 的一部分。它不仅是一个开源的,甚至 MS 团队也将其作为核心 JSON 序列化器。

1) Newtonsoft.Json(作为 Web.API 的一部分)已安装在您的解决方案中。所以你不必单独下载(nuget)。它总是在你的packages文件夹中。因此,使用属性只是添加引用。它在那里...

2)有一个小草稿如何做属性的东西,同时保留 POCO。正如我在这里尝试解释的那样:POCO's, behavior and Peristance Igorance,为了保持 POCO(例如,我们确实从数据层上的 NHibernate 的分层架构中受益),我们可以Contract Resolver. 我们的 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;
}
于 2013-05-23T18:10:09.920 回答
3

DropDownValues使用骆驼约定的类:

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

您可以使用前缀@来传递,但它仍然不遵循 C# 编码约定。

您可以避免保留关键字并仍然使用 C# 编码约定的更好的解决方案是使用CamelCasePropertyNamesContractResolver

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()
};
于 2013-05-23T02:40:47.030 回答