确保 .NET 中的 json 键是小写的

Posted

技术标签:

【中文标题】确保 .NET 中的 json 键是小写的【英文标题】:Ensuring json keys are lowercase in .NET 【发布时间】: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 在您的财产由一个词组成的情况下很有用。 嗯。我遇到了相反的问题......还有 - 你提到“用户名”是混合大小写的,这很有趣。您指的是“用户名”吗? 不只是需要保持混合大小写键的值只是我需要触摸的。值不要管。 【参考方案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);

注意事项-

使用string.ToLowerInvariant() 可确保在所有语言环境中生成相同的合同。

要控制覆盖的属性名、字典键和扩展数据名是否小写,可以将NamingStrategy.OverrideSpecifiedNamesNamingStrategy.ProcessDictionaryKeysNamingStrategy.ProcessExtensionDataNames(Json.NET 10.0.1及更高版本)设置为true .

您可能想cache the contract resolver for best performance。

如果您无法访问框架中的序列化程序设置,您可以将NamingStrategy 直接应用于您的对象,如下所示:

[JsonObject(NamingStrategyType = typeof(LowercaseNamingStrategy))]
public class Authority

    public string Username  get; set; 
    public string ApiToken  get; set; 

不要修改CamelCasePropertyNamesContractResolverNamingStrategy。此合约解析器在其所有实例之间全局共享类型信息,因此修改任何一个实例都可能产生意想不到的副作用。

【讨论】:

很好的答案,包含让序列化程序执行我想要的所有信息。特别是该做什么。很有用。非常感谢!【参考方案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()
        );

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

【讨论】:

以上是关于确保 .NET 中的 json 键是小写的的主要内容,如果未能解决你的问题,请参考以下文章

避免在asp.net json响应中自动小写首字母

.net core返回json首字母小写的问题解决

ASP.NET Core中返回 json 数据首字母大小写问题

Net Core中使用Newtonsoft.Json进行序列化保持原有大小写

.NET Core WebApi中返回 json 数据首字母大小写问题

csharp .net Rest Web Api Controller返回JSON格式大小写问题解决