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.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));
}
},
{
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/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/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());
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 _);
}
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
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..36a8d38e3 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)0)
)
)
)
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
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()
}
}
}
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..f83372131 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;
@@ -155,7 +155,7 @@ public static IEnumerable