113

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.

g t
  • 7,287
  • 7
  • 50
  • 85
Mark
  • 2,454
  • 4
  • 26
  • 29
  • Maybe the json serialization lib offers some kind of serialization attributes you could use to change the json-serialized names of your properties? – tdammers Jun 09 '11 at 06:02
  • @tdammers, thanks I'm trying to find something that does that, but so far unsuccessful. Hoping someone here could point me to it. – Mark Jun 09 '11 at 06:09
  • 1
    [This](http://stackoverflow.com/questions/2789593/force-lowercase-property-names-from-json-in-asp-net-mvc) can be useful in case you propety consists of one word. – Lipotam Jul 17 '12 at 14:17
  • Huh. I'm having the opposite problem... also -- it's funny that you mention "Username" is mixed case. Did you mean "UserName"? – BrainSlugs83 Oct 23 '15 at 07:56
  • No simply that the values needed to remain mixed case the keys Only were what I need to touch. Value leave alone. – Mark Oct 23 '15 at 21:46

6 Answers6

185

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.

rgripper
  • 1,066
  • 15
  • 23
alexn
  • 57,867
  • 14
  • 111
  • 145
  • any reasonable way to do this in reverse? For deserialization? – Shaun Rowan Mar 03 '12 at 21:42
  • Is there anyway to set these settings as default? – thomaux Jun 19 '12 at 09:45
  • 1
    @Anzeo I have not tried to do that myself, and I did not find any information about that in the documentation. A solution would be to wrap JsonConvert.SerializeObject in your own class. See my update. – alexn Jun 21 '12 at 07:48
  • 3
    It seems, this custom contractresolver does not take into account the JsonProperty attribute, if you want to specify exceptions... e.g. [JsonProperty("alternateName")] still gets lowercased or is there another way to do it ? – rekna Sep 29 '12 at 19:44
  • 2
    +1 for pointing out the `CamelCasePropertyNamesContractResolver`. Now I found `System.Net.Http.Formatting.JsonContractResolver` is the default in WebAPI and this class is internal. I endup with rewrite `JsonContractResolver` with camel case. Someone reported this to be public https://aspnetwebstack.codeplex.com/workitem/228 – CallMeLaNN May 19 '13 at 01:53
  • 12
    `CamelCasePropertyNamesContratResolver` do not transform the properties in lowercase, just the first char. – ToXinE Sep 18 '15 at 08:26
  • Nice solution! Any idea if I would like to implement it only for ONE WebAPI action? Thanks – Aleksander Bethke Aug 22 '16 at 16:07
  • How to camel case only first level of properties?? – Vlado Pandžić Nov 03 '17 at 08:25
24
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();
    }
}
Sagi
  • 8,972
  • 3
  • 33
  • 41
18

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 -

dbc
  • 104,963
  • 20
  • 228
  • 340
  • 1
    Great answer with all the information I needed to get the serializer to do what I wanted. Especially for what _not_ to do. Very useful. Thank you much! – Suncat2000 Oct 15 '21 at 19:12
12

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);
Jorgelig
  • 184
  • 2
  • 9
0

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.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
workabyte
  • 3,496
  • 2
  • 27
  • 35
0

As per Microsoft Documentation a simpler way could be used:

    var options = new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    };

    var json = JsonSerializer.Deserialize<Authority>(auth, options);