[BUG] [PHP] [Symfony] Several issues for parameters of type date-time
Bug Report Checklist
-
Have you provided a full/minimal spec to reproduce the issue? -
Have you validated the input using an OpenAPI validator (example)? -
Have you tested with the latest master to confirm the issue still exists? -
Have you searched for related issues/PRs? -
What's the actual output vs expected output? -
[Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When I declare a parameter of with type: string
and format: date-time
and generate a symfony bundle with it, then I observe that queries on that endpoint get a 400
response with message This value should be of type string
.
openapi-generator version
I've observed this behavior with openapi-generator 6.3.0, as well as on a version built from source with today's master branch (140d941d)
OpenAPI declaration file content or url
openapi: 3.0.1
info:
title: Test
version: 0.0.1
paths:
/my-route:
get:
summary: Get stuff
parameters:
- name: myparam
in: query
required: false
schema:
type: string
format: date-time
responses:
"200":
description: OK
Generation Details
java -jar openapi.jar generate -i openapi.yaml -g php-symfony -o out
Steps to reproduce
Plug the symfony bundle generated into a symfony app (following the steps in the auto-generated README). Then launch the symfony server and perform a query against this route, for instance:
curl -i http://localhost:8000/my-route # this should be ok because the parameter is marked as non required
# or also
curl -i 'http://localhost:8000/my-route?myparam=2017-07-21T17:32:28Z'
Expected behavior: I receive a 200
response.
Actual behavior: I receive a 400
response with content This value should be of type string`
Related issues/PRs
I've looked at https://github.com/OpenAPITools/openapi-generator/issues?q=is%3Aissue+symfony+date-time but those issues are not related to mine.
Suggest a fix
I think thos 3 changes may be needed to fix that issue:
- Currently the generated
Controller/DefaultController.php
looks like that:
// Read out all input parameter values into variables
$myparam = $request->query->get('myparam');
// Use the default value if no value was provided
// Deserialize the input values that needs it
try {
$myparam = $this->deserialize($myparam, '\DateTime', 'string');
} catch (SerializerRuntimeException $exception) {
return $this->createBadRequestResponse($exception->getMessage());
}
// Validate the input values
$asserts = [];
$asserts[] = new Assert\DateTime();
$response = $this->validate($myparam, $asserts);
if ($response instanceof Response) {
return $response;
}
Here we see that the validation occurs after the deserialization. That explains the issue observed since the validation expects $myparam
to be a string but it was already deserialized to DateTime. So I think the validation part should go before the deserialization, so that $myparam
would still be a string at the moment where it is checked.
-
In the snippet above we see that the generated code relies on Symfony's Symfony\Component\Validator\DateTime to perform the assertion, however that class checks against the format
Y-m-d H:i:s
though open api specification considers that date-time should conform to RFC 3339 which would be for instance2017-07-21T17:32:28Z
. So I think this check should be adapted as well (not sure by what it should be replaced though) -
The generated file
service/JmsSerializer.php
has a methoddeserializeString
which returnsnew DateTime($data)
for parameter of type date-time. But sincenew DateTime(null)
represents "now" it means that if the parameter is not provided by the query (which should be ok since I marked it has non required) then the deserialization would return "now" instead ofnull
. (perhaps this handling of null$data
should also be applied to other format of strings? I don't know)