From 69c4b775b4ebc8ca3939d8b994a7c17765a378a5 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:44:01 +0300 Subject: [PATCH 1/8] replace decimal.Parse with double.Parse for values greater than decimal's range; parse exclusivemax and min values as boolean types --- .../V2/JsonSchemaDeserializer.cs | 6 +++--- .../V2/OpenApiHeaderDeserializer.cs | 12 ++++++------ .../V2/OpenApiParameterDeserializer.cs | 6 +++--- .../V3/JsonSchemaDeserializer.cs | 6 +++--- .../V31/JsonSchemaDeserializer.cs | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/JsonSchemaDeserializer.cs index e2fea6cc4..52cfbd819 100644 --- a/src/Microsoft.OpenApi.Readers/V2/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/JsonSchemaDeserializer.cs @@ -30,13 +30,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)); } }, { @@ -48,7 +48,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/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiHeaderDeserializer.cs index 4d73cf4ef..4a0e2b1b4 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; @@ -55,25 +55,25 @@ internal static partial class OpenApiV2Deserializer { "maximum", (o, n) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().Maximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateHeaderSchemaBuilder().Maximum(double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { "exclusiveMaximum", (o, n) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMaximum(bool.Parse(n.GetScalarValue())); } }, { "minimum", (o, n) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().Minimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateHeaderSchemaBuilder().Minimum(double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { "exclusiveMinimum", (o, n) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateHeaderSchemaBuilder().ExclusiveMinimum(bool.Parse(n.GetScalarValue())); } }, { @@ -115,7 +115,7 @@ internal static partial class OpenApiV2Deserializer { "multipleOf", (o, n) => { - o.Schema = GetOrCreateHeaderSchemaBuilder().MultipleOf(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateHeaderSchemaBuilder().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 6aa59652d..5ca0779c7 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.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; @@ -72,13 +72,13 @@ internal static partial class OpenApiV2Deserializer { "minimum", (o, n) => { - o.Schema = GetOrCreateParameterSchemaBuilder().Minimum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateParameterSchemaBuilder().Minimum(double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { "maximum", (o, n) => { - o.Schema = GetOrCreateParameterSchemaBuilder().Maximum(decimal.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); + o.Schema = GetOrCreateParameterSchemaBuilder().Maximum(double.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)); } }, { diff --git a/src/Microsoft.OpenApi.Readers/V3/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/JsonSchemaDeserializer.cs index 2621d3729..49805ab04 100644 --- a/src/Microsoft.OpenApi.Readers/V3/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V3/JsonSchemaDeserializer.cs @@ -31,13 +31,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)); } }, { @@ -49,7 +49,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.Readers/V31/JsonSchemaDeserializer.cs b/src/Microsoft.OpenApi.Readers/V31/JsonSchemaDeserializer.cs index 2b1972824..a7d90ed1d 100644 --- a/src/Microsoft.OpenApi.Readers/V31/JsonSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V31/JsonSchemaDeserializer.cs @@ -31,31 +31,31 @@ internal static partial class OpenApiV31Deserializer { "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)); } }, { "exclusiveMaximum", (o, n) => { - o.ExclusiveMaximum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + o.ExclusiveMaximum(double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { "minimum", (o, n) => { - o.Minimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + o.Minimum(double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { "exclusiveMinimum", (o, n) => { - o.ExclusiveMinimum(decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); + o.ExclusiveMinimum(double.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)); } }, { From e5b63023364ccd4ac9c239c8f40eb7cc98ad3a11 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:48:20 +0300 Subject: [PATCH 2/8] Add support for double type by adding custom keywords to JsonSchemaBuilder and extension methods for fetching their values from the corresponding JSON schema --- .../Extensions/JsonSchemaBuilderExtensions.cs | 240 ++++++++++++++++++ .../Extensions/JsonSchemaExtensions.cs | 30 +++ .../Writers/OpenApiWriterBase.cs | 8 +- 3 files changed, 274 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs b/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs index e8d3a95c0..a1efeb615 100644 --- a/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/JsonSchemaBuilderExtensions.cs @@ -75,6 +75,66 @@ public static JsonSchemaBuilder ExclusiveMaximum(this JsonSchemaBuilder builder, return builder; } + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + /// + /// + /// + public static JsonSchemaBuilder Maximum(this JsonSchemaBuilder builder, double value) + { + builder.Add(new MaximumKeyword(value)); + return builder; + } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + /// + /// + /// + public static JsonSchemaBuilder Minimum(this JsonSchemaBuilder builder, double value) + { + builder.Add(new MinimumKeyword(value)); + return builder; + } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + /// + /// + /// + public static JsonSchemaBuilder ExclusiveMinimum(this JsonSchemaBuilder builder, double value) + { + builder.Add(new ExclusiveMinimumKeyword(value)); + return builder; + } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + /// + /// + /// + public static JsonSchemaBuilder ExclusiveMaximum(this JsonSchemaBuilder builder, double value) + { + builder.Add(new ExclusiveMaximumKeyword(value)); + return builder; + } + + /// + /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + /// + /// + /// + /// + public static JsonSchemaBuilder MultipleOf(this JsonSchemaBuilder builder, double value) + { + builder.Add(new MultipleOfKeyword(value)); + return builder; + } + /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 /// @@ -332,6 +392,186 @@ public void Evaluate(EvaluationContext context) } } + /// + /// The maximum keyword + /// + [SchemaKeyword(Name)] + public class MaximumKeyword : IJsonSchemaKeyword + { + /// + /// The schema keyword name + /// + public const string Name = "maximum"; + + /// + /// The ID. + /// + public double? Value { get; } + + /// + /// Creates a new . + /// + /// The 'maximum' value. + public MaximumKeyword(double value) + { + Value = value; + } + + /// + /// Implementation of IJsonSchemaKeyword interface + /// + /// + /// + public void Evaluate(EvaluationContext context) + { + throw new NotImplementedException(); + } + } + + /// + /// The ExclusiveMaximum keyword + /// + [SchemaKeyword(Name)] + public class ExclusiveMaximumKeyword : IJsonSchemaKeyword + { + /// + /// The schema keyword name + /// + public const string Name = "exclusiveMaximum"; + + /// + /// The ID. + /// + public double Value { get; } + + /// + /// Creates a new . + /// + /// The 'maximum' value. + public ExclusiveMaximumKeyword(double value) + { + Value = value; + } + + /// + /// Implementation of IJsonSchemaKeyword interface + /// + /// + /// + public void Evaluate(EvaluationContext context) + { + throw new NotImplementedException(); + } + } + + /// + /// The minimum keyword + /// + [SchemaKeyword(Name)] + public class MinimumKeyword : IJsonSchemaKeyword + { + /// + /// The schema keyword name + /// + public const string Name = "minimum"; + + /// + /// The ID. + /// + public double? Value { get; } + + /// + /// Creates a new . + /// + /// The`minimum` value. + public MinimumKeyword(double value) + { + Value = value; + } + + /// + /// Implementation of IJsonSchemaKeyword interface + /// + /// + /// + public void Evaluate(EvaluationContext context) + { + throw new NotImplementedException(); + } + } + + /// + /// The exclusive minimum keyword + /// + [SchemaKeyword(Name)] + public class ExclusiveMinimumKeyword : IJsonSchemaKeyword + { + /// + /// The schema keyword name + /// + public const string Name = "exclusiveMinimum"; + + /// + /// The ID. + /// + public double Value { get; } + + /// + /// Creates a new . + /// + /// Whether the`minimum` value should be considered exclusive. + public ExclusiveMinimumKeyword(double value) + { + Value = value; + } + + /// + /// Implementation of IJsonSchemaKeyword interface + /// + /// + /// + public void Evaluate(EvaluationContext context) + { + throw new NotImplementedException(); + } + } + + /// + /// The multipleOf keyword + /// + [SchemaKeyword(Name)] + public class MultipleOfKeyword : IJsonSchemaKeyword + { + /// + /// The schema keyword name + /// + public const string Name = "multipleOf"; + + /// + /// The ID. + /// + public double? Value { get; } + + /// + /// Creates a new . + /// + /// The `multipleOf` value. + public MultipleOfKeyword(double value) + { + Value = value; + } + + /// + /// Implementation of IJsonSchemaKeyword interface + /// + /// + /// + public void Evaluate(EvaluationContext context) + { + throw new NotImplementedException(); + } + } + /// /// The AdditionalPropertiesAllowed Keyword /// diff --git a/src/Microsoft.OpenApi/Extensions/JsonSchemaExtensions.cs b/src/Microsoft.OpenApi/Extensions/JsonSchemaExtensions.cs index 6c0545fc3..6cab7d0db 100644 --- a/src/Microsoft.OpenApi/Extensions/JsonSchemaExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/JsonSchemaExtensions.cs @@ -46,6 +46,36 @@ public static string GetSummary(this JsonSchema schema) return schema.TryGetKeyword(NullableKeyword.Name, out var k) ? k.Value! : null; } + /// + /// Gets the minimum value if it exists + /// + /// + /// + public static double? GetOpenApiMinimum(this JsonSchema schema) + { + return schema.TryGetKeyword(MinimumKeyword.Name, out var k) ? k.Value! : null; + } + + /// + /// Gets the maximum value if it exists + /// + /// + /// + public static double? GetOpenApiMaximum(this JsonSchema schema) + { + return schema.TryGetKeyword(MaximumKeyword.Name, out var k) ? k.Value! : null; + } + + /// + /// Gets the multipleOf value if it exists + /// + /// + /// + public static double? GetOpenApiMultipleOf(this JsonSchema schema) + { + return schema.TryGetKeyword(MultipleOfKeyword.Name, out var k) ? k.Value! : null; + } + /// /// Gets the additional properties value if it exists /// diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs index c07a88180..fa6416817 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterBase.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; @@ -470,16 +470,16 @@ public void WriteJsonSchemaWithoutReference(IOpenApiWriter writer, JsonSchema sc writer.WriteProperty(OpenApiConstants.Title, schema.GetTitle()); // multipleOf - writer.WriteProperty(OpenApiConstants.MultipleOf, schema.GetMultipleOf()); + writer.WriteProperty(OpenApiConstants.MultipleOf, schema.GetOpenApiMultipleOf()); // maximum - writer.WriteProperty(OpenApiConstants.Maximum, schema.GetMaximum()); + writer.WriteProperty(OpenApiConstants.Maximum, schema.GetOpenApiMaximum()); // exclusiveMaximum writer.WriteProperty(OpenApiConstants.ExclusiveMaximum, schema.GetOpenApiExclusiveMaximum()); // minimum - writer.WriteProperty(OpenApiConstants.Minimum, schema.GetMinimum()); + writer.WriteProperty(OpenApiConstants.Minimum, schema.GetOpenApiMinimum()); // exclusiveMinimum writer.WriteProperty(OpenApiConstants.ExclusiveMinimum, schema.GetOpenApiExclusiveMinimum()); From ddf372b52d5a04f843c05e89acf7912d66412ba6 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:49:02 +0300 Subject: [PATCH 3/8] Code refactor and cleanup --- .../ParseNodes/ParserHelper.cs | 35 ---- .../Helpers/SchemaSerializerHelper.cs | 150 +++++++++--------- .../Writers/IOpenApiWriter.cs | 4 +- .../SpecialCharacterStringExtensions.cs | 10 +- 4 files changed, 84 insertions(+), 115 deletions(-) delete mode 100644 src/Microsoft.OpenApi.Readers/ParseNodes/ParserHelper.cs diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/ParserHelper.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/ParserHelper.cs deleted file mode 100644 index 9dd05ebdd..000000000 --- a/src/Microsoft.OpenApi.Readers/ParseNodes/ParserHelper.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -using System; -using System.Globalization; - -namespace Microsoft.OpenApi.Readers.ParseNodes -{ - /// - /// Useful tools to parse data - /// - internal class ParserHelper - { - /// - /// Parses decimal in invariant culture. - /// If the decimal is too big or small, it returns the default value - /// - /// Note: sometimes developers put Double.MaxValue or Long.MaxValue as min/max values for numbers in json schema even if their numbers are not expected to be that big/small. - /// As we have already released the library with Decimal type for Max/Min, let's not introduce the breaking change and just fallback to Decimal.Max / Min. This should satisfy almost every scenario. - /// We can revisit this if somebody really needs to have double or long here. - /// - /// - public static decimal ParseDecimalWithFallbackOnOverflow(string value, decimal defaultValue) - { - try - { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); - } - catch (OverflowException) - { - return defaultValue; - } - } - } -} diff --git a/src/Microsoft.OpenApi/Helpers/SchemaSerializerHelper.cs b/src/Microsoft.OpenApi/Helpers/SchemaSerializerHelper.cs index 62a677432..128eaac09 100644 --- a/src/Microsoft.OpenApi/Helpers/SchemaSerializerHelper.cs +++ b/src/Microsoft.OpenApi/Helpers/SchemaSerializerHelper.cs @@ -19,81 +19,85 @@ internal static void WriteAsItemsProperties(JsonSchema schema, OpenApiSpecVersion version) { Utils.CheckArgumentNull(writer); - // type - if (schema.GetJsonType() != null) - { - writer.WritePropertyName(OpenApiConstants.Type); - var type = schema.GetJsonType().Value; - writer.WriteValue(OpenApiTypeMapper.ConvertSchemaValueTypeToString(type)); - } - - // format - var format = schema.GetFormat()?.Key; - if (string.IsNullOrEmpty(format)) - { - format = RetrieveFormatFromNestedSchema(schema.GetAllOf()) ?? RetrieveFormatFromNestedSchema(schema.GetOneOf()) - ?? RetrieveFormatFromNestedSchema(schema.GetAnyOf()); - } - writer.WriteProperty(OpenApiConstants.Format, format); - - // items - writer.WriteOptionalObject(OpenApiConstants.Items, schema.GetItems(), - (w, s) => w.WriteJsonSchema(s, version)); - - // collectionFormat - // We need information from style in parameter to populate this. - // The best effort we can make is to pull this information from the first parameter - // that leverages this schema. However, that in itself may not be as simple - // as the schema directly under parameter might be referencing one in the Components, - // so we will need to do a full scan of the object before we can write the value for - // this property. This is not supported yet, so we will skip this property at the moment. - - // default - if (schema.GetDefault() != null) - { - writer.WritePropertyName(OpenApiConstants.Default); - writer.WriteValue(schema.GetDefault()); - } - - // maximum - writer.WriteProperty(OpenApiConstants.Maximum, schema.GetMaximum()); - - // exclusiveMaximum - writer.WriteProperty(OpenApiConstants.ExclusiveMaximum, schema.GetExclusiveMaximum()); - - // minimum - writer.WriteProperty(OpenApiConstants.Minimum, schema.GetMinimum()); - // exclusiveMinimum - writer.WriteProperty(OpenApiConstants.ExclusiveMinimum, schema.GetExclusiveMinimum()); - - // maxLength - writer.WriteProperty(OpenApiConstants.MaxLength, schema.GetMaxLength()); - - // minLength - writer.WriteProperty(OpenApiConstants.MinLength, schema.GetMinLength()); - - // pattern - writer.WriteProperty(OpenApiConstants.Pattern, schema.GetPattern()?.ToString()); - - // maxItems - writer.WriteProperty(OpenApiConstants.MaxItems, schema.GetMaxItems()); - - // minItems - writer.WriteProperty(OpenApiConstants.MinItems, schema.GetMinItems()); - - // enum - if (schema.GetEnum() != null) + if (schema != null) { - writer.WritePropertyName(OpenApiConstants.Enum); - writer.WriteValue(schema.GetEnum()); - } - - // multipleOf - writer.WriteProperty(OpenApiConstants.MultipleOf, schema.GetMultipleOf()); - - // extensions - writer.WriteExtensions(extensions, OpenApiSpecVersion.OpenApi2_0); + // type + if (schema.GetJsonType() != null) + { + writer.WritePropertyName(OpenApiConstants.Type); + var type = schema.GetJsonType().Value; + writer.WriteValue(OpenApiTypeMapper.ConvertSchemaValueTypeToString(type)); + } + + // format + var format = schema.GetFormat()?.Key; + if (string.IsNullOrEmpty(format)) + { + format = RetrieveFormatFromNestedSchema(schema.GetAllOf()) ?? RetrieveFormatFromNestedSchema(schema.GetOneOf()) + ?? RetrieveFormatFromNestedSchema(schema.GetAnyOf()); + } + writer.WriteProperty(OpenApiConstants.Format, format); + + // items + writer.WriteOptionalObject(OpenApiConstants.Items, schema.GetItems(), + (w, s) => w.WriteJsonSchema(s, version)); + + // collectionFormat + // We need information from style in parameter to populate this. + // The best effort we can make is to pull this information from the first parameter + // that leverages this schema. However, that in itself may not be as simple + // as the schema directly under parameter might be referencing one in the Components, + // so we will need to do a full scan of the object before we can write the value for + // this property. This is not supported yet, so we will skip this property at the moment. + + // default + if (schema.GetDefault() != null) + { + writer.WritePropertyName(OpenApiConstants.Default); + writer.WriteValue(schema.GetDefault()); + } + + // maximum + writer.WriteProperty(OpenApiConstants.Maximum, schema.GetOpenApiMaximum()); + + // exclusiveMaximum + writer.WriteProperty(OpenApiConstants.ExclusiveMaximum, schema.GetOpenApiExclusiveMaximum()); + + // minimum + writer.WriteProperty(OpenApiConstants.Minimum, schema.GetOpenApiMinimum()); + + // exclusiveMinimum + writer.WriteProperty(OpenApiConstants.ExclusiveMinimum, schema.GetOpenApiExclusiveMinimum()); + + // maxLength + writer.WriteProperty(OpenApiConstants.MaxLength, schema.GetMaxLength()); + + // minLength + writer.WriteProperty(OpenApiConstants.MinLength, schema.GetMinLength()); + + // pattern + writer.WriteProperty(OpenApiConstants.Pattern, schema.GetPattern()?.ToString()); + + // maxItems + writer.WriteProperty(OpenApiConstants.MaxItems, schema.GetMaxItems()); + + // minItems + writer.WriteProperty(OpenApiConstants.MinItems, schema.GetMinItems()); + + // enum + if (schema.GetEnum() != null) + { + writer.WritePropertyName(OpenApiConstants.Enum); + writer.WriteValue(schema.GetEnum()); + } + + // multipleOf + writer.WriteProperty(OpenApiConstants.MultipleOf, schema.GetOpenApiMultipleOf()); + + // extensions + writer.WriteExtensions(extensions, OpenApiSpecVersion.OpenApi2_0); + } } private static string RetrieveFormatFromNestedSchema(IReadOnlyCollection schema) diff --git a/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs b/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs index 9da2b64e0..7f1decf59 100644 --- a/src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs +++ b/src/Microsoft.OpenApi/Writers/IOpenApiWriter.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; @@ -46,7 +46,7 @@ public interface IOpenApiWriter /// /// Write the decimal value. /// - void WriteValue(decimal value); + void WriteValue(double value); /// /// Write the int value. diff --git a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs index 708aa7237..2a41b8961 100644 --- a/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs @@ -158,10 +158,10 @@ 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 _) || - IsHexadecimalNotation(input) || + // If string can be mistaken as a number, c-style hexadouble 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 _) || + IsHexadoubleNotation(input) || bool.TryParse(input, out _) || DateTime.TryParse(input, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) { @@ -197,7 +197,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 _); } From 665fd4316b1e0e1370631990aff40c96216b064d Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:49:51 +0300 Subject: [PATCH 4/8] Add test to validate double.max and double.min values are parsed correctly --- .../V3Tests/OpenApiDocumentTests.cs | 25 +++++++++++++++++++ .../docWithDoubleMaxAndMinValues.yaml | 17 +++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithDoubleMaxAndMinValues.yaml diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 46ac9f815..569a36af9 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -9,8 +9,10 @@ using FluentAssertions; using Json.Schema; using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Tests; using Microsoft.OpenApi.Validations; using Microsoft.OpenApi.Validations.Rules; using Microsoft.OpenApi.Writers; @@ -1108,5 +1110,28 @@ public void ParseDocumentWithJsonSchemaReferencesWorks() actualSchema.Should().BeEquivalentTo(expectedSchema); } + [Fact] + public void ParseDocumentWithDoubleMaxAndMinValuesSucceeds() + { + // Arrange + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "docWithDoubleMaxAndMinValues.yaml")); + + // Act + var doc = new OpenApiStreamReader(new OpenApiReaderSettings + { + ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences + }).Read(stream, out var diagnostic); + var header = doc.Paths["/example"].Operations[OperationType.Get].Responses["200"].Headers["X-Rate-Limit"]; + var actualHeader = header.SerializeAsYaml(OpenApiSpecVersion.OpenApi2_0); + var serializedHeader = @"description: The maximum number of requests allowed in a given time window +type: integer +maximum: 1.7976931348623157E+308 +minimum: -1.7976931348623157E+308 +"; + + // Assert + actualHeader.MakeLineBreaksEnvironmentNeutral().Should() + .BeEquivalentTo(serializedHeader.MakeLineBreaksEnvironmentNeutral()); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithDoubleMaxAndMinValues.yaml b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithDoubleMaxAndMinValues.yaml new file mode 100644 index 000000000..d860c1371 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithDoubleMaxAndMinValues.yaml @@ -0,0 +1,17 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Example API +paths: + /example: + get: + summary: Example GET request + responses: + 200: + description: Successful response + headers: + X-Rate-Limit: + description: The maximum number of requests allowed in a given time window + type: integer + minimum: -1.7976931348623157E+308 + maximum: 1.7976931348623157E+308 \ No newline at end of file From 82cb11262219a61eb8b349504233936e20e5684e Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:50:15 +0300 Subject: [PATCH 5/8] Clean up tests --- .../ParseNodes/ParserHelperTests.cs | 25 ------------------- .../V3Tests/JsonSchemaTests.cs | 6 ++--- .../Models/OpenApiOperationTests.cs | 10 ++++---- 3 files changed, 8 insertions(+), 33 deletions(-) delete mode 100644 test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs diff --git a/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs b/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs deleted file mode 100644 index 1368e103d..000000000 --- a/test/Microsoft.OpenApi.Readers.Tests/ParseNodes/ParserHelperTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -using System.Globalization; -using Microsoft.OpenApi.Readers.ParseNodes; -using Xunit; - -namespace Microsoft.OpenApi.Readers.Tests.ParseNodes -{ - [Collection("DefaultSettings")] - public class ParserHelperTests - { - [Fact] - public void ParseDecimalWithFallbackOnOverflow_ReturnsParsedValue() - { - Assert.Equal(23434, ParserHelper.ParseDecimalWithFallbackOnOverflow("23434", 10)); - } - - [Fact] - public void ParseDecimalWithFallbackOnOverflow_Overflows_ReturnsFallback() - { - Assert.Equal(10, ParserHelper.ParseDecimalWithFallbackOnOverflow(double.MaxValue.ToString(CultureInfo.InvariantCulture), 10)); - } - } -} diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs index b37067e09..77b058984 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs @@ -234,7 +234,7 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() .Required("message", "code") .Properties( ("message", new JsonSchemaBuilder().Type(SchemaValueType.String)), - ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum(100).Maximum(600))), + ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum((double)100).Maximum((double) 600))), ["ExtendedErrorModel"] = new JsonSchemaBuilder() .Ref("#/components/schemas/ExtendedErrorModel") .AllOf( @@ -242,7 +242,7 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() .Ref("#/components/schemas/ErrorModel") .Type(SchemaValueType.Object) .Properties( - ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum(100).Maximum(600)), + ("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum((double)100).Maximum((double) 600)), ("message", new JsonSchemaBuilder().Type(SchemaValueType.String))) .Required("message", "code"), new JsonSchemaBuilder() @@ -330,7 +330,7 @@ public void ParseAdvancedSchemaWithReferenceShouldSucceed() .Format("int32") .Description("the size of the pack the dog is from") .Default(0) - .Minimum(0) + .Minimum(double.MinValue) ) ) ) diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index 283b3d8d2..79fec3421 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.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.Collections.Generic; @@ -46,7 +46,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum(5).Maximum(10).Build() + Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum((double)5).Maximum((double)10).Build() } } }, @@ -66,7 +66,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum(5).Maximum(10).Build() + Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum((double)5).Maximum((double)10).Build() } } } @@ -128,7 +128,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum(5).Maximum(10).Build() + Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum((double)5).Maximum((double)10).Build() } } }, @@ -148,7 +148,7 @@ public class OpenApiOperationTests { ["application/json"] = new() { - Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum(5).Maximum(10).Build() + Schema = new JsonSchemaBuilder().Type(SchemaValueType.Number).Minimum((double)5).Maximum((double)10).Build() } } } From ebc5228523da92a83435692bf1a4aa85040c3b46 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 20:53:04 +0300 Subject: [PATCH 6/8] Update API interface and writer tests --- .../PublicApi/PublicApi.approved.txt | 50 ++++++++++++++++++- .../Writers/OpenApiJsonWriterTests.cs | 2 +- .../Writers/OpenApiYamlWriterTests.cs | 4 +- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index b05748032..ab4e171cd 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -160,6 +160,22 @@ namespace Microsoft.OpenApi.Extensions where T : System.Attribute { } public static string GetDisplayName(this System.Enum enumValue) { } } + [Json.Schema.SchemaKeyword("exclusiveMaximum")] + public class ExclusiveMaximumKeyword : Json.Schema.IJsonSchemaKeyword + { + public const string Name = "exclusiveMaximum"; + public ExclusiveMaximumKeyword(double value) { } + public double Value { get; } + public void Evaluate(Json.Schema.EvaluationContext context) { } + } + [Json.Schema.SchemaKeyword("exclusiveMinimum")] + public class ExclusiveMinimumKeyword : Json.Schema.IJsonSchemaKeyword + { + public const string Name = "exclusiveMinimum"; + public ExclusiveMinimumKeyword(double value) { } + public double Value { get; } + public void Evaluate(Json.Schema.EvaluationContext context) { } + } [Json.Schema.SchemaKeyword("extensions")] public class ExtensionsKeyword : Json.Schema.IJsonSchemaKeyword { @@ -179,8 +195,13 @@ namespace Microsoft.OpenApi.Extensions public static Json.Schema.JsonSchemaBuilder AdditionalPropertiesAllowed(this Json.Schema.JsonSchemaBuilder builder, bool additionalPropertiesAllowed) { } public static Json.Schema.JsonSchemaBuilder Discriminator(this Json.Schema.JsonSchemaBuilder builder, Microsoft.OpenApi.Models.OpenApiDiscriminator discriminator) { } public static Json.Schema.JsonSchemaBuilder ExclusiveMaximum(this Json.Schema.JsonSchemaBuilder builder, bool value) { } + public static Json.Schema.JsonSchemaBuilder ExclusiveMaximum(this Json.Schema.JsonSchemaBuilder builder, double value) { } public static Json.Schema.JsonSchemaBuilder ExclusiveMinimum(this Json.Schema.JsonSchemaBuilder builder, bool value) { } + public static Json.Schema.JsonSchemaBuilder ExclusiveMinimum(this Json.Schema.JsonSchemaBuilder builder, double value) { } public static Json.Schema.JsonSchemaBuilder Extensions(this Json.Schema.JsonSchemaBuilder builder, System.Collections.Generic.IDictionary extensions) { } + public static Json.Schema.JsonSchemaBuilder Maximum(this Json.Schema.JsonSchemaBuilder builder, double value) { } + public static Json.Schema.JsonSchemaBuilder Minimum(this Json.Schema.JsonSchemaBuilder builder, double value) { } + public static Json.Schema.JsonSchemaBuilder MultipleOf(this Json.Schema.JsonSchemaBuilder builder, double value) { } public static Json.Schema.JsonSchemaBuilder Nullable(this Json.Schema.JsonSchemaBuilder builder, bool value) { } public static Json.Schema.JsonSchemaBuilder OpenApiExternalDocs(this Json.Schema.JsonSchemaBuilder builder, Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } public static Json.Schema.JsonSchemaBuilder Remove(this Json.Schema.JsonSchemaBuilder builder, string keyword) { } @@ -195,8 +216,35 @@ namespace Microsoft.OpenApi.Extensions public static bool? GetOpenApiExclusiveMaximum(this Json.Schema.JsonSchema schema) { } public static bool? GetOpenApiExclusiveMinimum(this Json.Schema.JsonSchema schema) { } public static Microsoft.OpenApi.Models.OpenApiExternalDocs GetOpenApiExternalDocs(this Json.Schema.JsonSchema schema) { } + public static double? GetOpenApiMaximum(this Json.Schema.JsonSchema schema) { } + public static double? GetOpenApiMinimum(this Json.Schema.JsonSchema schema) { } + public static double? GetOpenApiMultipleOf(this Json.Schema.JsonSchema schema) { } public static string GetSummary(this Json.Schema.JsonSchema schema) { } } + [Json.Schema.SchemaKeyword("maximum")] + public class MaximumKeyword : Json.Schema.IJsonSchemaKeyword + { + public const string Name = "maximum"; + public MaximumKeyword(double value) { } + public double? Value { get; } + public void Evaluate(Json.Schema.EvaluationContext context) { } + } + [Json.Schema.SchemaKeyword("minimum")] + public class MinimumKeyword : Json.Schema.IJsonSchemaKeyword + { + public const string Name = "minimum"; + public MinimumKeyword(double value) { } + public double? Value { get; } + public void Evaluate(Json.Schema.EvaluationContext context) { } + } + [Json.Schema.SchemaKeyword("multipleOf")] + public class MultipleOfKeyword : Json.Schema.IJsonSchemaKeyword + { + public const string Name = "multipleOf"; + public MultipleOfKeyword(double value) { } + public double? Value { get; } + public void Evaluate(Json.Schema.EvaluationContext context) { } + } [Json.Schema.SchemaKeyword("nullable")] public class NullableKeyword : Json.Schema.IJsonSchemaKeyword { @@ -1491,7 +1539,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); diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs index 784750ab6..556b52100 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs @@ -181,7 +181,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 ebbd78147..5827adeef 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.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; @@ -267,7 +267,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) From 944142aa3435eab056474ecbd67e8b6070c147d9 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 21:04:30 +0300 Subject: [PATCH 7/8] Add project reference to access string extension method --- .../Microsoft.OpenApi.Readers.Tests.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 38a37821a..3e8d28091 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 false @@ -30,6 +30,7 @@ + \ No newline at end of file From efce038a35ebb377b47f68675fcd4ce2f584ad65 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 13 Mar 2024 21:04:42 +0300 Subject: [PATCH 8/8] More cleanup --- .../V3Tests/JsonSchemaTests.cs | 2 +- .../Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs index 77b058984..36a8d38e3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs @@ -330,7 +330,7 @@ public void ParseAdvancedSchemaWithReferenceShouldSucceed() .Format("int32") .Description("the size of the pack the dog is from") .Default(0) - .Minimum(double.MinValue) + .Minimum((double)0) ) ) ) diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs index 5827adeef..f83372131 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiYamlWriterTests.cs @@ -155,7 +155,7 @@ public static IEnumerable WriteMapAsYamlShouldMatchExpectedTestCasesCo ["property1"] = "10.0", ["property2"] = "10", ["property3"] = "-5", - ["property4"] = 10.0M, + ["property4"] = (double)10.0M, ["property5"] = 10, ["property6"] = -5, ["property7"] = true, @@ -168,7 +168,7 @@ public static IEnumerable WriteMapAsYamlShouldMatchExpectedTestCasesCo property1: '10.0' property2: '10' property3: '-5' - property4: 10.0 + property4: 10 property5: 10 property6: -5 property7: true