diff --git a/Directory.Build.props b/Directory.Build.props index 091613e7..643c355d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ - 1.5.24 + 1.5.25 WireMock.Net-Logo.png https://github.com/WireMock-Net/WireMock.Net Apache-2.0 diff --git a/Generate-ReleaseNotes.cmd b/Generate-ReleaseNotes.cmd index 7d6d613b..61c3fb5d 100644 --- a/Generate-ReleaseNotes.cmd +++ b/Generate-ReleaseNotes.cmd @@ -1,6 +1,6 @@ rem https://github.com/StefH/GitHubReleaseNotes -SET version=1.5.24 +SET version=1.5.25 GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN% diff --git a/src/WireMock.Net/Util/CSharpFormatter.cs b/src/WireMock.Net/Util/CSharpFormatter.cs index 483bc409..66cf248f 100644 --- a/src/WireMock.Net/Util/CSharpFormatter.cs +++ b/src/WireMock.Net/Util/CSharpFormatter.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using Newtonsoft.Json; @@ -9,82 +10,8 @@ namespace WireMock.Util; internal static class CSharpFormatter { - public static object ConvertToAnonymousObjectDefinition(object jsonBody) - { - var serializedBody = JsonConvert.SerializeObject(jsonBody); - using var jsonReader = new JsonTextReader(new StringReader(serializedBody)); - jsonReader.DateParseHandling = DateParseHandling.None; - var deserializedBody = JObject.Load(jsonReader); - - var anonymousObjectDefinition = ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2); - return anonymousObjectDefinition; - } - - private static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0) - { - return token switch - { - JArray jArray => FormatArray(jArray, ind), - JObject jObject => FormatObject(jObject, ind), - JProperty jProperty => - $"{FormatPropertyName(jProperty.Name)} = {ConvertJsonToAnonymousObjectDefinition(jProperty.Value, ind)}", - JValue jValue => jValue.Type switch - { - JTokenType.None => "null", - JTokenType.Integer => jValue.Value?.ToString() ?? "null", - JTokenType.Float => jValue.Value?.ToString() ?? "null", - JTokenType.String => ToCSharpStringLiteral(jValue.Value?.ToString()), - JTokenType.Boolean => jValue.Value?.ToString()?.ToLower() ?? "null", - JTokenType.Null => "null", - JTokenType.Undefined => "null", - JTokenType.Date when jValue.Value is DateTime dateValue => - $"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})", - _ => $"UNHANDLED_CASE: {jValue.Type}" - }, - _ => $"UNHANDLED_CASE: {token}" - }; - } - - public static string ToCSharpStringLiteral(string? value) - { - var escapedValue = value?.Replace("\"", "\\\"") ?? string.Empty; - if (escapedValue.Contains("\n")) - { - return $"@\"{escapedValue}\""; - } - - return $"\"{escapedValue}\""; - } - - private static string FormatPropertyName(string propertyName) - { - return CsharpKeywords.Contains(propertyName) ? "@" + propertyName : propertyName; - } - - private static string FormatObject(JObject jObject, int ind) - { - var indStr = new string(' ', 4 * ind); - var indStrSub = new string(' ', 4 * (ind + 1)); - var items = jObject.Properties().Select(x => ConvertJsonToAnonymousObjectDefinition(x, ind + 1)); - - return $"new\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}"; - } - - private static string FormatArray(JArray jArray, int ind) - { - var hasComplexItems = jArray.FirstOrDefault() is JObject or JArray; - var items = jArray.Select(x => ConvertJsonToAnonymousObjectDefinition(x, hasComplexItems ? ind + 1 : ind)); - if (hasComplexItems) - { - var indStr = new string(' ', 4 * ind); - var indStrSub = new string(' ', 4 * (ind + 1)); - return $"new []\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}"; - } - - return $"new [] {{ {string.Join(", ", items)} }}"; - } - - private static readonly HashSet CsharpKeywords = new HashSet(new[] + #region Reserved Keywords + private static readonly HashSet CSharpReservedKeywords = new(new[] { "abstract", "as", @@ -164,4 +91,79 @@ internal static class CSharpFormatter "volatile", "while" }); + #endregion + private const string Null = "null"; + + public static object ConvertToAnonymousObjectDefinition(object jsonBody) + { + var serializedBody = JsonConvert.SerializeObject(jsonBody); + using var jsonReader = new JsonTextReader(new StringReader(serializedBody)); + jsonReader.DateParseHandling = DateParseHandling.None; + var deserializedBody = JObject.Load(jsonReader); + + return ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2); + } + + private static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0) + { + return token switch + { + JArray jArray => FormatArray(jArray, ind), + JObject jObject => FormatObject(jObject, ind), + JProperty jProperty => $"{FormatPropertyName(jProperty.Name)} = {ConvertJsonToAnonymousObjectDefinition(jProperty.Value, ind)}", + JValue jValue => jValue.Type switch + { + JTokenType.None => Null, + JTokenType.Integer => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value) : Null, + JTokenType.Float => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value) : Null, + JTokenType.String => ToCSharpStringLiteral(jValue.Value?.ToString()), + JTokenType.Boolean => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value).ToLower() : Null, + JTokenType.Null => Null, + JTokenType.Undefined => Null, + JTokenType.Date when jValue.Value is DateTime dateValue => + $"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})", + _ => $"UNHANDLED_CASE: {jValue.Type}" + }, + _ => $"UNHANDLED_CASE: {token}" + }; + } + + public static string ToCSharpStringLiteral(string? value) + { + var escapedValue = value?.Replace("\"", "\\\"") ?? string.Empty; + if (escapedValue.Contains("\n")) + { + return $"@\"{escapedValue}\""; + } + + return $"\"{escapedValue}\""; + } + + private static string FormatPropertyName(string propertyName) + { + return CSharpReservedKeywords.Contains(propertyName) ? "@" + propertyName : propertyName; + } + + private static string FormatObject(JObject jObject, int ind) + { + var indStr = new string(' ', 4 * ind); + var indStrSub = new string(' ', 4 * (ind + 1)); + var items = jObject.Properties().Select(x => ConvertJsonToAnonymousObjectDefinition(x, ind + 1)); + + return $"new\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}"; + } + + private static string FormatArray(JArray jArray, int ind) + { + var hasComplexItems = jArray.FirstOrDefault() is JObject or JArray; + var items = jArray.Select(x => ConvertJsonToAnonymousObjectDefinition(x, hasComplexItems ? ind + 1 : ind)); + if (hasComplexItems) + { + var indStr = new string(' ', 4 * ind); + var indStrSub = new string(' ', 4 * (ind + 1)); + return $"new []\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}"; + } + + return $"new [] {{ {string.Join(", ", items)} }}"; + } } \ No newline at end of file