Ensuring json keys are lowercase in .NET
Is there simple way using JSON in .NET to ensure that the keys are sent as lower case?
At the moment I'm using the newtonsoft's Json.NET library and simply using
string loginRequest = JsonConvert.SerializeObject(auth);
In this case auth
is just the following object
public class Authority
{
public string Username { get; set; }
public string ApiToken { get; set; }
}
This results in
{"Username":"Mark","ApiToken":"xyzABC1234"}
Is there a way to ensure that the username
and apitoken
keys come through as lowercase?
I don't want to simply run it through String.ToLower()
of course because the values for username
and apitoken
are mixed case.
I realise I can programatically do this and create the JSON string manually, but I need this for approx 20 or so JSON data strings and I'm seeing if I can save myself some time. I'm wondering if there are any already built libraries that allow you to enforce lowercase for key creation.
Solution 1:
You can create a custom contract resolver for this. The following contract resolver will convert all keys to lowercase:
public class LowercaseContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToLower();
}
}
Usage:
var settings = new JsonSerializerSettings();
settings.ContractResolver = new LowercaseContractResolver();
var json = JsonConvert.SerializeObject(authority, Formatting.Indented, settings);
Wil result in:
{"username":"Mark","apitoken":"xyzABC1234"}
If you always want to serialize using the LowercaseContractResolver
, consider wrapping it in a class to avoid repeating yourself:
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();
}
}
}
Which can be used like this:
var json = LowercaseJsonSerializer.SerializeObject(new { Foo = "bar" });
// { "foo": "bar" }
ASP.NET MVC4 / WebAPI
If you are using ASP.NET MVC4 / WebAPI, you can use a CamelCasePropertyNamesContractResolver
from Newtonsoft.Json library which included by default.
Solution 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();
}
}
Solution 3:
In Json.NET 9.0.1 and later it is possible to ensure that all property names are converted to lowercase by using a custom NamingStrategy
. This class extracts the logic for algorithmic remapping of property names from the contract resolver to a separate, lightweight object that can be set on DefaultContractResolver.NamingStrategy
.
Doing so avoids the need to create a custom ContractResolver
and thus may be easier to integrate into frameworks that already have their own contract resolvers.
Define LowercaseNamingStrategy
as follows:
public class LowercaseNamingStrategy : NamingStrategy
{
protected override string ResolvePropertyName(string name)
{
return name.ToLowerInvariant();
}
}
Then serialize as follows:
var settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver { NamingStrategy = new LowercaseNamingStrategy() },
};
string loginRequest = JsonConvert.SerializeObject(auth, settings);
Notes -
Using
string.ToLowerInvariant()
ensures that the same contract is generated in all locales.To control whether overridden property names, dictionary keys and extension data names are lowercased, you can set
NamingStrategy.OverrideSpecifiedNames
,NamingStrategy.ProcessDictionaryKeys
orNamingStrategy.ProcessExtensionDataNames
(Json.NET 10.0.1 and later) totrue
.You may want to cache the contract resolver for best performance.
-
If you do not have access to the serializer settings in your framework, you can apply a
NamingStrategy
directly to your object as follows:[JsonObject(NamingStrategyType = typeof(LowercaseNamingStrategy))] public class Authority { public string Username { get; set; } public string ApiToken { get; set; } }
Do not modify the
NamingStrategy
ofCamelCasePropertyNamesContractResolver
. This contract resolver shares type information globally across all of its instances, and so modifying any one instance can have unexpected side effects.
Solution 4:
you can use "JsonProperty":
Usage:
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);
Solution 5:
For me I used a combination of some of the other answers and ended up with this
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
was closer to a solution to what I was looking for as I was not looking to create my own