Newton CamelCase Underline Problem

I noticed that when I serialize a C # dictionary having the HTTP_VERB key, it turns into httP_VERB in the JSON structure instead of hTTP_VERB or http_verb. I expected a camel case to do this.

This is the code I use to reproduce the problem:

class Program { static void Main(string[] args) { var settings = new JsonSerializerSettings(); settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); settings.NullValueHandling = NullValueHandling.Ignore; var headers = new Dictionary<string, string>(); headers["SessionID"] = "123456"; headers["HTTP_VERB"] = "POST"; headers["HTTPVERSION"] = "1"; var data = new { headers = headers }; string serializedEvent = JsonConvert.SerializeObject(data, settings); if (serializedEvent.Contains("httP_VERB")) { Console.WriteLine("Something is wrong with this camel case"); } else { Console.WriteLine("Sucess"); } } } 
+4
source share
2 answers

There is no way to make CamelCasePropertyNamesContractResolver convert strings to camel case the way you want, but you can easily write your own ContractResolver .

I used the PascalCase transform in a CsCss project. After a little adaptation, here is the result:

 public enum IdentifierCase { Camel, Pascal, } public class CustomPropertyNamesContractResolver : DefaultContractResolver { private static readonly CultureInfo Culture = CultureInfo.InvariantCulture; public CustomPropertyNamesContractResolver (bool shareCache = false) : base(shareCache) { Case = IdentifierCase.Camel; PreserveUnderscores = true; } public IdentifierCase Case { get; set; } public bool PreserveUnderscores { get; set; } protected override string ResolvePropertyName (string propertyName) { return ChangeCase(propertyName); } private string ChangeCase (string s) { var sb = new StringBuilder(s.Length); bool isNextUpper = Case == IdentifierCase.Pascal, isPrevLower = false; foreach (var c in s) { if (c == '_') { if (PreserveUnderscores) sb.Append(c); isNextUpper = true; } else { sb.Append(isNextUpper ? char.ToUpper(c, Culture) : isPrevLower ? c : char.ToLower(c, Culture)); isNextUpper = false; isPrevLower = char.IsLower(c); } } return sb.ToString(); } // Json.NET implementation for reference private static string ToCamelCase (string s) { if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0])) return s; var sb = new StringBuilder(); for (int i = 0; i < s.Length; ++i) { if (i == 0 || i + 1 >= s.Length || char.IsUpper(s[i + 1])) sb.Append(char.ToLower(s[i], Culture)); else { sb.Append(s.Substring(i)); break; } } return sb.ToString(); } } 

This converter supports both PascalCase and camelCase . It seems to convert property names the way you expect.

I left the oroginal ToCamelCase function from Json.NET for reference.

Program Example:

 internal class Program { private static void Main () { var obj = new Dictionary<string, string> { { "SessionID", "123456" }, { "HTTP_VERB", "POST" }, { "HTTPVERSION", "1" }, }; var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, ContractResolver = new CustomPropertyNamesContractResolver() }; string strCamel = JsonConvert.SerializeObject(obj, settings); Console.WriteLine("camelCase: \n" + strCamel); Console.WriteLine(strCamel.Contains("httP_VERB") ? "Something is wrong with this camel case" : "Success"); settings.ContractResolver = new CustomPropertyNamesContractResolver { Case = IdentifierCase.Pascal, PreserveUnderscores = false, }; string strPascal = JsonConvert.SerializeObject(obj, settings); Console.WriteLine("PascalCase: \n" + strPascal); Console.ReadKey(); } } 

Output:

 camelCase: { "sessionId": "123456", "http_Verb": "POST", "httpversion": "1" } Success PascalCase: { "SessionId": "123456", "HttpVerb": "POST", "Httpversion": "1" } 
+11
source

I needed to resolve in the reverse order, that is, lowercase underlined properties in JSON for Pascal-case non-underlined properties in .NET. Discord's solution helped me do this:

 public class PascalCasePropertyNamesContractResolver : DefaultContractResolver { private static readonly CultureInfo Culture = CultureInfo.InvariantCulture; public PascalCasePropertyNamesContractResolver(bool shareCache = false) : base(shareCache) { } protected override string ResolvePropertyName(string s) { var sb = new StringBuilder(s.Length); bool isNextUpper = false, isPrevLower = false; for (var i = 0; i < s.Length; i++) { var c = s[i]; sb.Append(char.ToLower(c, Culture)); isNextUpper = i + 1 < s.Length && char.IsUpper(s[i + 1]); if (isNextUpper && isPrevLower) { sb.Append("_"); } isPrevLower = char.IsLower(c); } return sb.ToString(); } } 
+1
source

Source: https://habr.com/ru/post/1502353/


All Articles