52

I'm using Newtonsoft Json.net to parse the JSON string. I convert the string into the JObject. When access the value of the element by the key, I want to the comparison is case-insensitive. In the code below, I use "FROM" as the key. I want it returns string "1" at the line json["FROM"].ToString(). But it fails. Is it possible to make the code below work?

String ptString = "{from: 1, to: 3}"; var json = (JObject)JsonConvert.DeserializeObject(ptString); String f = json["FROM"].ToString(); 
3
  • 1
    Refer to this answer that this is wanted according the JSON-RPC spec (keys are case sensitive!). Commented Aug 21, 2012 at 13:30
  • Couldnt you create some logic with .toUpper or .toLower in one of the ends? Commented Aug 21, 2012 at 15:36
  • 1
    You really should consider updating the accepted answer to the top voted one: stackoverflow.com/a/20475542/67824 Commented Oct 10, 2018 at 13:42

2 Answers 2

145

This should work:

var json = @"{UPPER: 'value'}"; var jObj = JObject.Parse(json); var upper = jObj.GetValue("upper", StringComparison.OrdinalIgnoreCase)?.Value<string>(); Console.WriteLine(upper); // value 
Sign up to request clarification or add additional context in comments.

4 Comments

Same thing does not seem to be available for the SelectToken methods.
Yeah, I had to manually get the JToken ignoring the casing, then find it's parent name in order to set a property while ignoring property name casing.
I used this answer and altered slightly to: var value = o.GetValue("upper", StringComparison.OrdinalIgnoreCase)?.Value<string>(); to handle null reference exception for when the key is not in the json.
Not valid for JArray: System.InvalidCastException : Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken
19

c# allows you to use dictionaries with keys that are case insensitive, so a workaround I've used is to convert the JObject to a dictionary with StringComparer.CurrentCultureIgnoreCase set, like so:

JObject json = (JObject)JsonConvert.DeserializeObject(ptString); Dictionary<string, object> d = new Dictionary<string, object>(json.ToObject<IDictionary<string, object>>(), StringComparer.CurrentCultureIgnoreCase); String f = d["FROM"].ToString(); 

4 Comments

The downside of this approach is that you lose the ability of getting anything below "level 1", meaning you cant get any nested property.
I don't see that so much of a downside. Unless you are not using an Azure API or auto generated Swagger JSON, there should be little to no issue with the depth. All of that is calculated and classes are created to handle the nesting in the correct order. This adds a slight amount of overhead depending on the object, but overall, I find this to be quite useful. In my case, the documentation that the Web Client was created from changed their property casing... again. Since they don't adhere to their own "contract," something like this prevents me having to go back and fix the code each time.
I'd suggest using this instead: var dictionary = new Dictionary<string, JToken>(jo.ToObject<IDictionary<string, JToken>>(), StringComparer.CurrentCultureIgnoreCase) as it allows the use of .ToObject<T> on the returned value, unlike the answer.
Only one level ? not for key/path "first.second" ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.