Search code examples
c#jsonjson.netcase-insensitive

Case insensitive access of JSON keys


I am trying to update json(depth > 2) file using Newtonsoft library. While reading the file, if json keys case are not same as in json file, it failed to fetch its value.

Sample JSON file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Error",
      "Microsoft.Hosting": "Error"
    }
  },
}

Sample C# Code:

                using (file)
            {
                var serializer = new JsonSerializer();
                var json = null;
                using (var streamReader = new StreamReader(file))
                {
                    using (var reader = new JsonTextReader(streamReader))
                    {
                        try
                        {
                            json = serializer.Deserialize(reader) as JObject;
                        }
                        catch (Exception e)
                        {

                        }
                    }
                }

Now, I am trying to access keys following way:

json["Logging"]["LogLevel"]["microsoft"] 

However, it failed to fetch as 'microsoft' key is in lower case i.e. different case as in json file. I tried searching on web but results shows Newtonsoft lib is by default case-insensitive. However, It doesn't seem to be working in my case. Am I missing syntax to access keys? Please suggest.


Solution

  • The deserializer is case insensitive by default. See this example :

    var text = """
        { "sOmEthIng": "Hi, world!" }
        """;
    
    Console.WriteLine(JsonConvert.DeserializeObject<Foo>(text).SoMetHing);
    
    class Foo
    {
        public string SoMetHing { get; set; }
    }
    

    But in your case, you use Newtonsoft.Json.Linq... where some method are case sensitive. For example, JObject.this[string propertyName] :

    public JToken? this[string propertyName]
    {
        get
        {
            JProperty? property = Property(propertyName, StringComparison.Ordinal);
            return property?.Value;
        }
    }
    

    This explicitly use StringComparison.Ordinal that is case sensitive.


    A alternative, it's to use a method that you case specify the case sensibility, like JObject.Property :

    var text = """"
            {
          "Logging": {
            "LogLevel": {
              "Default": "Information",
              "Microsoft": "Error",
              "Microsoft.Hosting": "Error"
            }
          },
        }
        """";
    
    var root = JsonConvert.DeserializeObject(text) as JObject;
    
    var logging = root.Property("logging", StringComparison.InvariantCultureIgnoreCase).Value as JObject;
    var logLevel = logging.Property("loglevel", StringComparison.InvariantCultureIgnoreCase).Value as JObject;
    var microsoft = (logLevel.Property("microsoft", StringComparison.InvariantCultureIgnoreCase).Value as JValue).Value as string;
    
    Console.WriteLine(microsoft);