diff --git a/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs b/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs index 6aefbf947..2c0a45379 100644 --- a/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs +++ b/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs @@ -157,7 +157,7 @@ public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny, OpenApiS } else { - if (type == "integer" && format == "int32") + if (type is "integer" or "number" && format == "int32") { if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) { @@ -165,7 +165,7 @@ public static IOpenApiAny GetSpecificOpenApiAny(IOpenApiAny openApiAny, OpenApiS } } - if (type == "integer" && format == "int64") + if (type is "integer" or "number" && format == "int64") { if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index b85add3ff..03f42a3a0 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs @@ -16,10 +16,10 @@ public static class OpenApiTypeMapper { [typeof(bool)] = () => new() { Type = "boolean" }, [typeof(byte)] = () => new() { Type = "string", Format = "byte" }, - [typeof(int)] = () => new() { Type = "integer", Format = "int32" }, - [typeof(uint)] = () => new() { Type = "integer", Format = "int32" }, - [typeof(long)] = () => new() { Type = "integer", Format = "int64" }, - [typeof(ulong)] = () => new() { Type = "integer", Format = "int64" }, + [typeof(int)] = () => new() { Type = "number", Format = "int32" }, + [typeof(uint)] = () => new() { Type = "number", Format = "int32" }, + [typeof(long)] = () => new() { Type = "number", Format = "int64" }, + [typeof(ulong)] = () => new() { Type = "number", Format = "int64" }, [typeof(float)] = () => new() { Type = "number", Format = "float" }, [typeof(double)] = () => new() { Type = "number", Format = "double" }, [typeof(decimal)] = () => new() { Type = "number", Format = "double" }, @@ -31,10 +31,10 @@ public static class OpenApiTypeMapper // Nullable types [typeof(bool?)] = () => new() { Type = "boolean", Nullable = true }, [typeof(byte?)] = () => new() { Type = "string", Format = "byte", Nullable = true }, - [typeof(int?)] = () => new() { Type = "integer", Format = "int32", Nullable = true }, - [typeof(uint?)] = () => new() { Type = "integer", Format = "int32", Nullable = true }, - [typeof(long?)] = () => new() { Type = "integer", Format = "int64", Nullable = true }, - [typeof(ulong?)] = () => new() { Type = "integer", Format = "int64", Nullable = true }, + [typeof(int?)] = () => new() { Type = "number", Format = "int32", Nullable = true }, + [typeof(uint?)] = () => new() { Type = "number", Format = "int32", Nullable = true }, + [typeof(long?)] = () => new() { Type = "number", Format = "int64", Nullable = true }, + [typeof(ulong?)] = () => new() { Type = "number", Format = "int64", Nullable = true }, [typeof(float?)] = () => new() { Type = "number", Format = "float", Nullable = true }, [typeof(double?)] = () => new() { Type = "number", Format = "double", Nullable = true }, [typeof(decimal?)] = () => new() { Type = "number", Format = "double", Nullable = true }, @@ -98,8 +98,9 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema var type = (schema.Type?.ToLowerInvariant(), schema.Format?.ToLowerInvariant(), schema.Nullable) switch { ("boolean", null, false) => typeof(bool), - ("integer", "int32", false) => typeof(int), - ("integer", "int64", false) => typeof(long), + // integer is technically not valid with format, but we must provide some compatibility + ("integer" or "number", "int32", false) => typeof(int), + ("integer" or "number", "int64", false) => typeof(long), ("integer", null, false) => typeof(int), ("number", "float", false) => typeof(float), ("number", "double", false) => typeof(double), @@ -113,8 +114,8 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema ("string", null, false) => typeof(string), ("object", null, false) => typeof(object), ("string", "uri", false) => typeof(Uri), - ("integer", "int32", true) => typeof(int?), - ("integer", "int64", true) => typeof(long?), + ("integer" or "number", "int32", true) => typeof(int?), + ("integer" or "number", "int64", true) => typeof(long?), ("integer", null, true) => typeof(int?), ("number", "float", true) => typeof(float?), ("number", "double", true) => typeof(double?), diff --git a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs index 4fdc6d2cf..8052892da 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs @@ -134,7 +134,7 @@ public static void ValidateDataTypeMismatch( return; } - if (type == "integer" && format == "int32") + if (type is "integer" or "number" && format == "int32") { if (value is not OpenApiInteger) { @@ -146,7 +146,7 @@ public static void ValidateDataTypeMismatch( return; } - if (type == "integer" && format == "int64") + if (type is "integer" or "number" && format == "int64") { if (value is not OpenApiLong) { @@ -158,7 +158,7 @@ public static void ValidateDataTypeMismatch( return; } - if (type == "integer" && value is not OpenApiInteger) + if (type is "integer" && value is not OpenApiInteger) { if (value is not OpenApiInteger) { diff --git a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs index ee6d6e658..44a4bcdb4 100644 --- a/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs +++ b/test/Microsoft.OpenApi.Tests/Extensions/OpenApiTypeMapperTests.cs @@ -14,7 +14,7 @@ public class OpenApiTypeMapperTests { public static IEnumerable PrimitiveTypeData => new List { - new object[] { typeof(int), new OpenApiSchema { Type = "integer", Format = "int32" } }, + new object[] { typeof(int), new OpenApiSchema { Type = "number", Format = "int32" } }, new object[] { typeof(string), new OpenApiSchema { Type = "string" } }, new object[] { typeof(double), new OpenApiSchema { Type = "number", Format = "double" } }, new object[] { typeof(float?), new OpenApiSchema { Type = "number", Format = "float", Nullable = true } }, @@ -24,6 +24,7 @@ public class OpenApiTypeMapperTests public static IEnumerable OpenApiDataTypes => new List { new object[] { new OpenApiSchema { Type = "integer", Format = "int32"}, typeof(int) }, + new object[] { new OpenApiSchema { Type = "number", Format = "int32"}, typeof(int) }, new object[] { new OpenApiSchema { Type = "integer", Format = null, Nullable = false}, typeof(int) }, new object[] { new OpenApiSchema { Type = "integer", Format = null, Nullable = true}, typeof(int?) }, new object[] { new OpenApiSchema { Type = "string" }, typeof(string) },