【问题标题】:Ensuring json keys are lowercase in .NET确保 .NET 中的 json 键是小写的
【发布时间】:2011-09-11 10:22:54
【问题描述】:

有没有简单的方法在 .NET 中使用 JSON 来确保密钥以小写形式发送?

目前我正在使用 newtonsoft 的 Json.NET 库并简单地使用

string loginRequest = JsonConvert.SerializeObject(auth);

在这种情况下,auth 就是下面的对象

public class Authority
{
    public string Username { get; set; }
    public string ApiToken { get; set; }
}

这会导致

{"Username":"Mark","ApiToken":"xyzABC1234"}

有没有办法确保usernameapitoken 键以小写形式出现?

我当然不想简单地通过String.ToLower() 运行它,因为usernameapitoken 的值是大小写混合的。

我意识到我可以以编程方式执行此操作并手动创建 JSON 字符串,但我需要大约 20 个左右的 JSON 数据字符串,我正在看看是否可以节省一些时间。我想知道是否有任何已经构建的库允许您强制使用小写来创建密钥。

【问题讨论】:

  • 也许 json 序列化库提供了某种序列化属性,您可以使用它来更改属性的 json 序列化名称?
  • @tdammers,谢谢,我正在尝试找到可以做到这一点的东西,但到目前为止还没有成功。希望这里有人可以指出我。
  • This 在您的财产由一个词组成的情况下很有用。
  • 嗯。我遇到了相反的问题......还有 - 你提到“用户名”是混合大小写的,这很有趣。您指的是“用户名”吗?
  • 不只是需要保持混合大小写键的值只是我需要触摸的。值不要管。

标签: .net json json.net


【解决方案1】:

您可以为此创建自定义合同解析器。以下合约解析器会将所有键转换为小写:

public class LowercaseContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        return propertyName.ToLower();
    }
}

用法:

var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.SerializeObject(authority, Formatting.Indented, settings);

将导致:

{"username":"Mark","apitoken":"xyzABC1234"}

如果您总是想使用LowercaseContractResolver 进行序列化,请考虑将其包装在一个类中以避免重复:

public class LowercaseJsonSerializer
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        ContractResolver = new LowercaseContractResolver()
    };

    public static string SerializeObject(object o)
    {
        return JsonConvert.SerializeObject(o, Formatting.Indented, Settings);
    }

    public class LowercaseContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return propertyName.ToLower();
        }
    }
}

可以这样使用:

var json = LowercaseJsonSerializer.SerializeObject(new { Foo = "bar" });
// { "foo": "bar" }

ASP.NET MVC4 / WebAPI

如果您使用的是 ASP.NET MVC4 / WebAPI,您可以使用默认包含的 Newtonsoft.Json 库中的 CamelCasePropertyNamesContractResolver

【讨论】:

  • 有什么合理的方法可以反过来吗?反序列化?
  • @Anzeo 我自己没有尝试过这样做,我也没有在文档中找到任何相关信息。一种解决方案是将 JsonConvert.SerializeObject 包装在您自己的类中。查看我的更新。
  • 看来,这个自定义contractresolver没有考虑到JsonProperty属性,如果你想指定例外......例如[JsonProperty("alternateName")] 仍然小写还是有其他方法可以做到这一点?
  • +1 用于指出CamelCasePropertyNamesContractResolver。现在我发现System.Net.Http.Formatting.JsonContractResolver 是WebAPI 中的默认值,而这个类是内部的。我最终用骆驼案重写JsonContractResolver。有人举报这是公开的aspnetwebstack.codeplex.com/workitem/228
  • CamelCasePropertyNamesContratResolver 不转换属性为小写,只转换第一个字符。
【解决方案2】:
protected void Application_Start() {
    JsonConfig.Configure();   
}

public static class JsonConfig
{
    public static void Configure(){
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;

        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}

【讨论】:

    【解决方案3】:

    Json.NET 9.0.1 及更高版本中,可以使用自定义NamingStrategy 确保所有属性名称都转换为小写。此类从合约解析器中提取属性名称的算法重映射逻辑到一个单独的轻量级对象,该对象可以在DefaultContractResolver.NamingStrategy 上设置。 这样做避免了创建custom ContractResolver 的需要,因此可能更容易集成到已经拥有自己的合约解析器的框架中。

    如下定义LowercaseNamingStrategy

    public class LowercaseNamingStrategy : NamingStrategy
    {
        protected override string ResolvePropertyName(string name)
        {
            return name.ToLowerInvariant();
        }
    }
    

    然后序列化如下:

    var settings = new JsonSerializerSettings
    {
        ContractResolver = new DefaultContractResolver { NamingStrategy = new LowercaseNamingStrategy() },
    };
    string loginRequest = JsonConvert.SerializeObject(auth, settings);
    

    注意事项-

    【讨论】:

    • 很好的答案,包含让序列化程序执行我想要的所有信息。特别是该做什么。很有用。非常感谢!
    【解决方案4】:

    你可以使用“JsonProperty”:

    用法:

    public class Authority
    {
        [JsonProperty("userName")] // or [JsonProperty("username")]
        public string Username { get; set; }
        [JsonProperty("apiToken")] // or [JsonProperty("apitoken")]
        public string ApiToken { get; set; }
    }
    
    var json  = JsonConvert.SerializeObject(authority);
    

    【讨论】:

      【解决方案5】:

      对我来说,我结合了其他一些答案,最终得到了这个

              return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
              {
                  ContractResolver = new CamelCasePropertyNamesContractResolver()
              });
      

      更接近于我正在寻找的解决方案,因为我不想创建自己的

      【讨论】:

        猜你喜欢
        • 2011-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-07
        • 2021-04-25
        • 2019-12-15
        • 1970-01-01
        • 2011-05-19
        相关资源
        最近更新 更多