From 122afba9908832bd5ac207164ee6c303bfd65cf1 Mon Sep 17 00:00:00 2001 From: Kristof Mattei Date: Sat, 21 Oct 2017 21:10:03 -0700 Subject: [PATCH] Updated StringUtils.ToCamelCase to fix an edge case. (#1467) --- .../Utilities/StringUtilsTests.cs | 4 +++ Src/Newtonsoft.Json/Utilities/StringUtils.cs | 31 ++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Utilities/StringUtilsTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/StringUtilsTests.cs index ef1b7737..85ff1865 100644 --- a/Src/Newtonsoft.Json.Tests/Utilities/StringUtilsTests.cs +++ b/Src/Newtonsoft.Json.Tests/Utilities/StringUtilsTests.cs @@ -64,6 +64,10 @@ namespace Newtonsoft.Json.Tests.Utilities Assert.AreEqual("shoutinG_CASE", StringUtils.ToCamelCase("SHOUTING_CASE")); Assert.AreEqual("9999-12-31T23:59:59.9999999Z", StringUtils.ToCamelCase("9999-12-31T23:59:59.9999999Z")); Assert.AreEqual("hi!! This is text. Time to test.", StringUtils.ToCamelCase("Hi!! This is text. Time to test.")); + Assert.AreEqual("building", StringUtils.ToCamelCase("BUILDING")); + Assert.AreEqual("building Property", StringUtils.ToCamelCase("BUILDING Property")); + Assert.AreEqual("building Property", StringUtils.ToCamelCase("Building Property")); + Assert.AreEqual("building PROPERTY", StringUtils.ToCamelCase("BUILDING PROPERTY")); } [Test] diff --git a/Src/Newtonsoft.Json/Utilities/StringUtils.cs b/Src/Newtonsoft.Json/Utilities/StringUtils.cs index aaf6c2d8..049c70a7 100644 --- a/Src/Newtonsoft.Json/Utilities/StringUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/StringUtils.cs @@ -165,21 +165,38 @@ namespace Newtonsoft.Json.Utilities bool hasNext = (i + 1 < chars.Length); if (i > 0 && hasNext && !char.IsUpper(chars[i + 1])) { + // if the next character is a space, which is not considered uppercase + // (otherwise we wouldn't be here...) + // we want to ensure that the following: + // 'FOO bar' is rewritten as 'foo bar', and not as 'foO bar' + // The code was written in such a way that the first word in uppercase + // ends when if finds an uppercase letter followed by a lowercase letter. + // now a ' ' (space, (char)32) is considered not upper + // but in that case we still want our current character to become lowercase + if (char.IsSeparator(chars[i + 1])) + { + chars[i] = ToLower(chars[i]); + } + break; } - char c; -#if HAVE_CHAR_TO_STRING_WITH_CULTURE - c = char.ToLower(chars[i], CultureInfo.InvariantCulture); -#else - c = char.ToLowerInvariant(chars[i]); -#endif - chars[i] = c; + chars[i] = ToLower(chars[i]); } return new string(chars); } + private static char ToLower(char c) + { +#if HAVE_CHAR_TO_STRING_WITH_CULTURE + c = char.ToLower(c, CultureInfo.InvariantCulture); +#else + c = char.ToLowerInvariant(c); +#endif + return c; + } + internal enum SnakeCaseState { Start,