From 159271032f793d91b7976413e94174aac5e43dcc Mon Sep 17 00:00:00 2001 From: Afsal Rahman Date: Tue, 13 Dec 2022 22:19:34 +0530 Subject: [PATCH] replace decimal.Parse with double.Parse to include support for parsing values exceeding range of decimal --- .../V2/OpenApiHeaderDeserializer.cs | 8 ++++---- .../V2/OpenApiParameterDeserializer.cs | 4 ++-- .../V2/OpenApiSchemaDeserializer.cs | 6 +++--- .../V3/OpenApiSchemaDeserializer.cs | 6 +++--- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 6 +++--- src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs | 4 ++-- src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs | 6 ++++-- .../Writers/SpecialCharacterStringExtensions.cs | 12 +++++++----- .../V2Tests/OpenApiDocumentTests.cs | 4 ++-- .../V3Tests/OpenApiDocumentTests.cs | 4 ++-- .../PublicApi/PublicApi.approved.txt | 11 ++++++----- .../Writers/OpenApiJsonWriterTests.cs | 2 +- .../Writers/OpenApiYamlWriterTests.cs | 2 +- 13 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs index 5d6cc2ff3..436ae1ca3 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -57,7 +57,7 @@ internal static partial class OpenApiV2Deserializer { "maximum", (o, n) => { - GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); + GetOrCreateSchema(o).Maximum = double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); } }, { @@ -69,7 +69,7 @@ internal static partial class OpenApiV2Deserializer { "minimum", (o, n) => { - GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); + GetOrCreateSchema(o).Minimum = double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); } }, { @@ -117,7 +117,7 @@ internal static partial class OpenApiV2Deserializer { "multipleOf", (o, n) => { - GetOrCreateSchema(o).MultipleOf = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); + GetOrCreateSchema(o).MultipleOf = double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); } }, { diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs index 5be08c71e..38ab18639 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs @@ -82,13 +82,13 @@ internal static partial class OpenApiV2Deserializer { "minimum", (o, n) => { - GetOrCreateSchema(o).Minimum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); + GetOrCreateSchema(o).Minimum = double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); } }, { "maximum", (o, n) => { - GetOrCreateSchema(o).Maximum = decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); + GetOrCreateSchema(o).Maximum = double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture); } }, { diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs index 0878eda9a..cb2c563bf 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiSchemaDeserializer.cs @@ -26,13 +26,13 @@ internal static partial class OpenApiV2Deserializer { "multipleOf", (o, n) => { - o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.MultipleOf = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { "maximum", (o, n) => { - o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.Maximum = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { @@ -44,7 +44,7 @@ internal static partial class OpenApiV2Deserializer { "minimum", (o, n) => { - o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.Minimum = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs index 60727c4bb..3c85e4561 100644 --- a/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiSchemaDeserializer.cs @@ -27,13 +27,13 @@ internal static partial class OpenApiV3Deserializer { "multipleOf", (o, n) => { - o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.MultipleOf = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { "maximum", (o, n) => { - o.Maximum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.Maximum = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { @@ -45,7 +45,7 @@ internal static partial class OpenApiV3Deserializer { "minimum", (o, n) => { - o.Minimum = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); + o.Minimum = double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture); } }, { diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 513b865df..b00419d85 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -41,7 +41,7 @@ public class OpenApiSchema : IOpenApiSerializable, IOpenApiReferenceable, IEffec /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 /// - public decimal? Maximum { get; set; } + public double? Maximum { get; set; } /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 @@ -51,7 +51,7 @@ public class OpenApiSchema : IOpenApiSerializable, IOpenApiReferenceable, IEffec /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 /// - public decimal? Minimum { get; set; } + public double? Minimum { get; set; } /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 @@ -77,7 +77,7 @@ public class OpenApiSchema : IOpenApiSerializable, IOpenApiReferenceable, IEffec /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 /// - public decimal? MultipleOf { get; set; } + public double? MultipleOf { get; set; } /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 diff --git a/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs b/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs index 8fcbf10ed..7d086806e 100644 --- a/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs +++ b/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs @@ -39,9 +39,9 @@ public interface IOpenApiWriter void WriteValue(string value); /// - /// Write the decimal value. + /// Write the double value. /// - void WriteValue(decimal value); + void WriteValue(double value); /// /// Write the int value. diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs index 4d7f11032..bfac14f67 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs @@ -148,9 +148,11 @@ public virtual void WriteValue(double value) } /// - /// Write decimal value. + /// Write + /// + /// value. /// - /// The decimal value. + /// The double value. public virtual void WriteValue(decimal value) { WriteValueSeparator(); diff --git a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs index 6e1ea2beb..56eda2937 100644 --- a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs @@ -187,10 +187,12 @@ internal static string GetYamlCompatibleString(this string input) return $"'{input}'"; } - // If string can be mistaken as a number, c-style hexadecimal notation, a boolean, or a timestamp, - // wrap it in quote to indicate that this is indeed a string, not a number, c-style hexadecimal notation, a boolean, or a timestamp - if (decimal.TryParse(input, NumberStyles.Float, CultureInfo.InvariantCulture, out var _) || - IsHexadecimalNotation(input) || + // If string can be mistaken as a number, c-style hexa + // + // notation, a boolean, or a timestamp, + // wrap it in quote to indicate that this is indeed a string, not a number, c-style hexadouble notation, a boolean, or a timestamp + if (double.TryParse(input, NumberStyles.Float, CultureInfo.InvariantCulture, out var _) || + IsHexadoubleNotation(input) || bool.TryParse(input, out var _) || DateTime.TryParse(input, CultureInfo.InvariantCulture, DateTimeStyles.None, out var _)) { @@ -227,7 +229,7 @@ internal static string GetJsonCompatibleString(this string value) return $"\"{value}\""; } - internal static bool IsHexadecimalNotation(string input) + internal static bool IsHexadoubleNotation(string input) { return input.StartsWith("0x") && int.TryParse(input.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var _); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index fcf0471ea..8eec661b0 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -134,8 +134,8 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) ["sampleProperty"] = new OpenApiSchema() { Type = "double", - Minimum = (decimal)100.54, - Maximum = (decimal)60000000.35, + Minimum = (double)100.54, + Maximum = (double)60000000.35, ExclusiveMaximum = true, ExclusiveMinimum = false } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 362609291..29322fb41 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -157,8 +157,8 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) ["sampleProperty"] = new OpenApiSchema() { Type = "double", - Minimum = (decimal)100.54, - Maximum = (decimal)60000000.35, + Minimum = (double)100.54, + Maximum = (double)60000000.35, ExclusiveMaximum = true, ExclusiveMinimum = false } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index db3a3ecf7..2133e3a17 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -853,12 +853,13 @@ namespace Microsoft.OpenApi.Models public int? MaxItems { get; set; } public int? MaxLength { get; set; } public int? MaxProperties { get; set; } - public decimal? Maximum { get; set; } + public + ? Maximum { get; set; } public int? MinItems { get; set; } public int? MinLength { get; set; } public int? MinProperties { get; set; } - public decimal? Minimum { get; set; } - public decimal? MultipleOf { get; set; } + public double? Minimum { get; set; } + public double? MultipleOf { get; set; } public Microsoft.OpenApi.Models.OpenApiSchema Not { get; set; } public bool Nullable { get; set; } public System.Collections.Generic.IList OneOf { get; set; } @@ -1404,7 +1405,7 @@ namespace Microsoft.OpenApi.Writers void WriteStartArray(); void WriteStartObject(); void WriteValue(bool value); - void WriteValue(decimal value); + void WriteValue(double value); void WriteValue(int value); void WriteValue(object value); void WriteValue(string value); @@ -1467,7 +1468,7 @@ namespace Microsoft.OpenApi.Writers public virtual void WriteValue(bool value) { } public virtual void WriteValue(System.DateTime value) { } public virtual void WriteValue(System.DateTimeOffset value) { } - public virtual void WriteValue(decimal value) { } + public virtual void WriteValue(double value) { } public virtual void WriteValue(double value) { } public virtual void WriteValue(int value) { } public virtual void WriteValue(long value) { } diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs index 44d1be55b..0317bfb12 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs @@ -188,7 +188,7 @@ private void WriteValueRecursive(OpenApiJsonWriter writer, object value) { if (value == null || value.GetType().IsPrimitive - || value is decimal + || value is double || value is string || value is DateTimeOffset || value is DateTime) diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index bfaa3da51..fc29bbe94 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -256,7 +256,7 @@ private void WriteValueRecursive(OpenApiYamlWriter writer, object value) { if (value == null || value.GetType().IsPrimitive - || value is decimal + || value is double || value is string || value is DateTimeOffset || value is DateTime)