-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Respect default context in DateTimeNormalizer::denormalize #43329
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
Conversation
This comment has been minimized.
This comment has been minimized.
608f56f
to
569bf07
Compare
674a7bd
to
763ea05
Compare
I targeted the wrong branch so the milestone is now wrong. |
We could preserve $defaultDateTimeErrors, and hint about it when the constructor fallback fails too.
We could argue the formatted value in a raw payload is already validated, before being passed to a deserializer :) That said, i think the datetime-constructor-as-fallback is a generally fine approach, for what is an implementation detail. If you get a DateTime, your value is denormalized. edit: it also enables robustness-principle by default :) |
Can you elaborate on that the raw payload is already validated? Are there a "normal apporch" to use a validator with the raw payload? In my real world example I deserialize some JSON payload into a object then I validate it with symfony validator. I have had to override DateTimeNormalizer to catch any errors which are later cough by a custom date validator I made.
That seems like a good solution to at the least provide some hints about the default context format failing. |
Im still on a mission to shift the paradigm :) #43047 (comment) "validation before hydration" benefits object design IMHO. |
@@ -113,6 +113,16 @@ public function denormalize($data, $type, $format = null, array $context = []) | |||
throw new NotNormalizableValueException(sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count'])."\n".implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors']))); | |||
} | |||
|
|||
$defaultDateTimeFormat = $this->defaultContext[self::FORMAT_KEY] ?? null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't you patch L97 to this instead?
$dateTimeFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY] ?? null;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we allow createFromFormat from defaultContext[FORMAT_KEY] to fail due BC, but generally we can't assume the default format fits all payloads
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we trigger a deprecation in case the fallback path is triggered, so we can remove it in Symfony 7+ to enforce the defaultContext[FORMAT_KEY]
is honored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symfony 7 is released. Is it planned to remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet as far as I can see. The first step to remove something in the next major release would be to deprecate it in a minor release before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With additional deprecation as mentioned in https://github.com/symfony/symfony/pull/43329/files#r812202044
@hultberg Are you still interested in finishing this PR? It looks like we are almost there. |
Well, this targets 4.4 as a bug fix, so we cannot add the deprecation I suggested. So this should be ready to merge as is. |
I added the deprecation and opened the discussion in #47095 |
Thank you @hultberg. |
Hey there. 👋
I'm bringing my first code patch to symfony today and it's for fixing a bug I encountered today while working with DateTimeNormalizer. In my project I have set a default date format in the service container and I noticed that the denormalized date did not follow my set date format (I enforce time but the serialized date did not contain the time stamp which should have failed when using DateTime::createFromDate). After some debugging I discovered the issue described in issue #29030
DateTimeNormalizer::normalize
respects the date time format in context or default context whileDateTimeNormalizer::denormalize
only respects the former. This patch adds logic to denormalize too attempt create a DateTime object from the default context format (by default set to\DateTime::RFC3339
) with createFromFormat and then if that fails continue on with the current behaviour. In my opinion this patch does not break the symfony BC promise as it simply adds another way to denormalize the date time.One issue: There are no error handling when creating the date time from default context as the logic just continues on which might give the impression to the developer that the denormalization with the specific format worked correctly. I was not able to find a way to handle any error and keeping BC.
Future tough: At some point the
new DateTime
call in denormalize should be deprecated since creating a date time with createFromFormat is considered "safer" in my eyes as it's very explicit while the call tonew DateTime
is implicit about the date format and must perform parsing and guessing of the intended format (explained over at https://www.php.net/manual/en/datetime.formats.php). Another thing aboutnew DateTime
is the terriable error handling as you must catch a\Exception
which means you catch "what ever" exception that can exist, even\ErrorException
since\ErrorException extends \Exception
.Fixes #29030
Alternative PR (closed) #33813