确保JSON键在.NET中为小写


103

是否有简单的方法在.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 2011年

@tdammers,谢谢,我正在尝试找到能做到这一点的东西,但到目前为止没有成功。希望有人在这里指向我。
马克

1
如果您的支持由一个单词组成,可能会很有用。
利波坦

嗯 我遇到的是相反的问题,也...您提到“用户名”是大小写混合的,这很有趣。您是说“用户名”吗?
BrainSlugs83

不仅仅需要保持混合的值,还需要按键。价值休假一个人。
马克

Answers:


176

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

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,则可以使用CamelCasePropertyNamesContractResolverNewtonsoft.Json库,该库默认包含。


有任何合理的方法可以做到这一点吗?是否需要反序列化?
肖恩·罗恩

1
@Anzeo我自己没有尝试这样做,并且我在文档中没有找到有关此信息。一种解决方案是将JsonConvert.SerializeObject包装在您自己的类中。查看我的更新。
alexn

3
看来,如果您要指定异常,则此自定义的contractresolver不会考虑JsonProperty属性,例如[JsonProperty(“ alternateName”)]仍然是小写的,或者还有另一种方法吗?
rekna 2012年

2
+1指出CamelCasePropertyNamesContractResolver。现在,我发现System.Net.Http.Formatting.JsonContractResolverWebAPI中的默认值是该类,并且是内部类。我最终用JsonContractResolver骆驼案重写。有人报告这是公开的aspnetwebstack.codeplex.com/workitem/228
CallMeLaNN

10
CamelCasePropertyNamesContratResolver请勿以小写形式转换属性,只需转换第一个字符即可。
ToXinE

23
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();
    }
}

10

Json.NET 9.0.1和更高版本中,可以确保通过使用custom将所有属性名称都转换为小写NamingStrategy。此类从合同解析器中提取用于属性名称的算法重映射的逻辑,该逻辑可以设置为一个单独的轻量级对象DefaultContractResolver.NamingStrategy。这样做避免了创建自定义的需求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);

注意事项-


8

您可以使用“ 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);

0

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

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

由于我不想创建自己的解决方案,因此更接近于我所寻找的解决方案

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.