-
Notifications
You must be signed in to change notification settings - Fork 270
Description
Describe the bug
I have a toy API that exists for testing ASP.NET Core functionality, and one of the resources describes times and acts like a clock.
The schema for the response of this endpoint is below:
"TimeResponse": {
"type": "object",
"properties": {
"timestamp": {
"type": "string",
"description": "The timestamp for the response for which the times are generated.",
"format": "date-time"
},
"rfc1123": {
"type": "string",
"description": "The current UTC date and time in RFC1123 format."
},
"unix": {
"type": "integer",
"description": "The number of seconds since the UNIX epoch.",
"format": "int64"
},
"universalSortable": {
"type": "string",
"description": "The current UTC date and time in universal sortable format."
},
"universalFull": {
"type": "string",
"description": "The current UTC date and time in universal full format."
}
},
"description": "Represents the response from the /time API resource."
}This response explicitly has:
- One
date-timefor ISO-8601 - One
int64for Unix timestamps - Three
stringproperties that are string representations of dates that do not conform to ISO-8601
It also contains the following JSON example for the schema:
"example": {
"timestamp": "2016-06-03T18:44:14+00:00",
"rfc1123": "Fri, 03 Jun 2016 18:44:14 GMT",
"unix": 1464979454,
"universalSortable": "2016-06-03 18:44:14Z",
"universalFull": "Friday, 03 June 2016 18:44:14"
}The example is valid for the moment in time that it describes.
If the schema is validated according to the validation rules with code such as the below, it generates 4 validation warnings:
[Fact]
public void SchemaGeneratesNoValidateWarnings()
{
using var streamReader = new StreamReader("openapi.json");
var reader = new OpenApiStreamReader();
var document = reader.Read(streamReader.BaseStream, out var diagnostic);
var errors = document.Validate(ValidationRuleSet.GetDefaultRuleSet());
Assert.Empty(errors);
}[
Data and type mismatch found. [#/paths/~1time/get/responses/200/content/application~1json/example/rfc1123],
Data and type mismatch found. [#/paths/~1time/get/responses/200/content/application~1json/example/unix],
Data and type mismatch found. [#/paths/~1time/get/responses/200/content/application~1json/example/universalSortable],
Data and type mismatch found. [#/paths/~1time/get/responses/200/content/application~1json/example/universalFull]
]
For the three "date-ish" values, this is because this line of code treats the value as an OpenApiDateTime as it happens to parse as a DateTimeOffset:
OpenAPI.NET/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs
Lines 64 to 73 in 6899d5f
| // More narrow type detection for explicit strings, only check types that are passed as strings | |
| if (schema == null) | |
| { | |
| if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTimeValue)) | |
| { | |
| // if the time component is exactly midnight(00:00:00) meaning no time has elapsed, return a date-only value | |
| return dateTimeValue.TimeOfDay == TimeSpan.Zero ? new OpenApiDate(dateTimeValue.Date) | |
| : new OpenApiDateTime(dateTimeValue); | |
| } | |
| } |
This then fires the validation warning here as the type test fails:
OpenAPI.NET/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs
Lines 256 to 266 in 306dda2
| if (type == "string") | |
| { | |
| if (!(value is OpenApiString)) | |
| { | |
| context.CreateWarning( | |
| ruleName, | |
| DataTypeMismatchedErrorMessage); | |
| } | |
| return; | |
| } |
For the int64 value, because the value is less than int.MaxValue + 1, this code treats the value as an int32:
OpenAPI.NET/src/Microsoft.OpenApi.Readers/ParseNodes/OpenApiAnyConverter.cs
Lines 138 to 146 in 6899d5f
| if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intValue)) | |
| { | |
| return new OpenApiInteger(intValue); | |
| } | |
| if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) | |
| { | |
| return new OpenApiLong(longValue); | |
| } |
This then causes the type test to fail in a similar fashion:
OpenAPI.NET/src/Microsoft.OpenApi/Validations/Rules/RuleHelpers.cs
Lines 148 to 158 in 306dda2
| if (type == "integer" && format == "int64") | |
| { | |
| if (!(value is OpenApiLong)) | |
| { | |
| context.CreateWarning( | |
| ruleName, | |
| DataTypeMismatchedErrorMessage); | |
| } | |
| return; | |
| } |
OpenApi File To Reproduce
Expected behavior
The example is valid according to the schema, so should not generate any validation warnings.
Screenshots/Code Snippets
N/A
Additional context
Found through use of Kiota to generate a typed C# client for the OpenAPI schema as part of dotnet/aspnetcore#56318 (comment).