Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: The JSON value could not be converted to System.DateOnly #2920

Closed
Bidou44 opened this issue May 28, 2024 · 12 comments
Closed

[Bug]: The JSON value could not be converted to System.DateOnly #2920

Bidou44 opened this issue May 28, 2024 · 12 comments
Labels
bug help-wanted A change up for grabs for contributions from the community
Milestone

Comments

@Bidou44
Copy link

Bidou44 commented May 28, 2024

Describe the bug

Everything was working fine with v6.5.0. After migrating to v6.6.1 or v6.6.2, I got the following exception

System.Text.Json.JsonException: The JSON value could not be converted to System.DateOnly.

I didn't change any line of code, just migrated the package.

Expected behavior

the json definition should load correctly. Instead, I got an error message.

Actual behavior

This is what I get

{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "An unhandled exception occurred",
    "instance": "/api/doc/v1.json",
    "traceId": "f0b3b9ac7ca1e1711f1ebfbb291f8385",
    "exception": "Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate Operation for action - (...). See inner exception\n ---> Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Failed to generate schema for type - (...). See inner exception\n ---> System.Text.Json.JsonException: The JSON value could not be converted to System.DateOnly.\n   at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)\n   at System.Text.Json.JsonSerializer.UnboxOnWrite[T](Object value)\n   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsObject(Utf8JsonWriter writer, Object rootValue)\n   at System.Text.Json.JsonSerializer.WriteStringAsObject(Object value, JsonTypeInfo jsonTypeInfo)\n   at Swashbuckle.AspNetCore.SwaggerGen.JsonSerializerDataContractResolver.JsonConverterFunc(Object value, Type type)\n   at Swashbuckle.AspNetCore.SwaggerGen.JsonSerializerDataContractResolver.<>c__DisplayClass2_0.<GetDataContractForType>b__1(Object value)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateDefaultValue(DataContract dataContract, Type modelType, Object defaultValue)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForMember(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, DataProperty dataProperty)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.CreateObjectSchema(DataContract dataContract, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.<>c__DisplayClass11_0.<GenerateConcreteSchema>b__3()\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateReferencedSchema(DataContract dataContract, SchemaRepository schemaRepository, Func`1 definitionFactory)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchemaForParameter(Type modelType, SchemaRepository schemaRepository, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)\n   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGenerator.GenerateSchema(Type modelType, SchemaRepository schemaRepository, MemberInfo memberInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)\n   --- End of inner exception stack trace ---\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateSchema(Type type, SchemaRepository schemaRepository, PropertyInfo propertyInfo, ParameterInfo parameterInfo, ApiParameterRouteInfo routeInfo)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateRequestBodyFromBodyParameter(ApiDescription apiDescription, SchemaRepository schemaRepository, ApiParameterDescription bodyParameter)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateRequestBody(ApiDescription apiDescription, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)\n   --- End of inner exception stack trace ---\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerDocumentWithoutFilters(String documentName, String host, String basePath)\n   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(String documentName, String host, String basePath)\n   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)\n   at (...)
}

Steps to reproduce

No response

Exception(s) (if any)

System.Text.Json.JsonException: The JSON value could not be converted to System.DateOnly.

Swashbuckle.AspNetCore version

6.6.1 and upper

.NET Version

net8.0

Anything else?

No response

@Bidou44 Bidou44 added the bug label May 28, 2024
@martincostello
Copy link
Collaborator

Swashbuckle.AspNetCore 6.6 added support for the DateOnly type which was previously unknown to it as part of adding support for .NET 8.

Could you share an example of what value is trying to be (de)serialized to a DateOnly value and/or an API definition that causes this issue?

@martincostello martincostello added the needs-repro A minimal reproducible example is needed label May 28, 2024
@Bidou44
Copy link
Author

Bidou44 commented May 28, 2024

Unfortunately I don't have a minimal working example right now.
The Dto that is referenced in the exception looks like this, I don't know if that helps:

public class MyDto
{
    public DateOnly ActiveFrom { get; set; } = DateTimeHelper.Today;

    public DateOnly? InactiveFrom { get; set; }

    (...)
}

@martincostello
Copy link
Collaborator

I think the missing piece for us what is the string that's trying to be turned into a DateOnly - if it's genuinely invalid, then it might be that it was invalid before but just happened to work because it was just being treated as a string. Now with the knowledge of DateOnly, the existing invalid value is now being surfaced.

@Bidou44
Copy link
Author

Bidou44 commented May 28, 2024

I understand your question but I don't know. I'm not doing any api calls, I'm just trying to load the swagger page where all APIs are listed http://localhost:8080/swagger/ui and the exception pops up. Was working fine with v6.5.0

How can I find the value it's trying to convert to DateOnly?

@martincostello
Copy link
Collaborator

I think the only way to get to the bottom of it is to provide a minimal repro project you can share with us that we can then debug. Alternatively, you could clone this repo and reference the project from source rather than NuGet and step through the code to where the exception is coming from.

@Bidou44
Copy link
Author

Bidou44 commented May 31, 2024

After a long debugging, I finally found the problem:

public class MyDto
{
    public DateOnly ActiveFrom { get; set; }

    [DefaultValue(null)]
    public DateOnly? InactiveFrom { get; set; }
}

The problem here comes from the [DefaultValue(null)]. Was working fine with v6.5.0, breaks with 6.6.1.

Hope it helps.
Cheers.

@martincostello
Copy link
Collaborator

For clarity, does it work if you update to 6.6.2, or is it broken with that too?

@Bidou44
Copy link
Author

Bidou44 commented May 31, 2024

No, it doesn't work with this version either.

I think we had this attribute so that the default value displayed in Swagger UI would not be filled (otherwise a random string would be displayed). It probably worked because for swagger DateOnly was handled like a "string" (?)
Now that 6.6.1 and upper supports DateOnly, perhaps the attribute is no longer needed to have an empty default value (when the type is nullable of course) ? I'll test it next week...

@martincostello martincostello removed the needs-repro A minimal reproducible example is needed label May 31, 2024
@Bidou44
Copy link
Author

Bidou44 commented Jun 3, 2024

Removing that attribute fixed the problem, but then you have a default value in Swagger UI, which is probably not the default you want for a nullable value (but that is ok, I guess it always worked like this). But with version 6.5 and earlier you were able to have that behavior by applying the DefaultValue attribute. With 6.6.1 and later an exception is thrown, so a breaking change was introduced here.

Any fix soon?

@martincostello
Copy link
Collaborator

I haven't had the time to look into it yet.

Community contributions to investigate the bug and/or fix are welcome as it would speed things along.

@martincostello martincostello added the help-wanted A change up for grabs for contributions from the community label Jun 3, 2024
@jgarciadelanoceda
Copy link
Contributor

I am probably going to look at this issue

@martincostello
Copy link
Collaborator

#2941

@martincostello martincostello added this to the v6.7.0 milestone Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug help-wanted A change up for grabs for contributions from the community
Projects
None yet
Development

No branches or pull requests

3 participants