-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] DateTimeNormalizer handling of null and empty values (returning it instead of new object) #25287
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
[Serializer] DateTimeNormalizer handling of null and empty values (returning it instead of new object) #25287
Conversation
c95353a
to
6292a6b
Compare
Travis failure is unrelated |
public function testDenormalizeWithNullAndEmptyString() | ||
{ | ||
$this->assertNull($this->normalizer->denormalize(null, \DateTimeInterface::class)); | ||
$this->assertEmpty($this->normalizer->denormalize('', \DateTimeInterface::class)); |
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.
assertSame(''
@@ -67,6 +67,10 @@ public function denormalize($data, $class, $format = null, array $context = arra | |||
{ | |||
$dateTimeFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : null; | |||
|
|||
if (empty($data)) { |
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.
Could be too broad? Should should only null
? Should we also really check the empty string?
@dunglas any hint?
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.
I agree. Maybe should we just tweak the supportDenormalization
function to skip this normalizer is the value isn't a string.
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.
And we keep the test on empty strings or do we add it in the supportDenormalization
?
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.
isn't that a BC ?
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.
done, added to supportDenorm and modifed the denormalize
94f5658
to
233ad77
Compare
@@ -67,6 +67,7 @@ public function testSupportsDenormalization() | |||
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTime::class)); | |||
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTimeImmutable::class)); | |||
$this->assertFalse($this->normalizer->supportsDenormalization('foo', 'Bar')); | |||
$this->assertFalse($this->normalizer->supportsDenormalization(null, \DateTimeImmutable::class)); |
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.
What does this mean? If not denormalizer supports the "thing", what happens? 🤔
@sroze AFAIK it will return null if no normalizer supports it.
|
even if it’s null ?
Le mar. 5 déc. 2017 à 11:51, Maxime Steinhausser <notifications@github.com>
a écrit :
… @Simperfit <https://github.com/simperfit> , @sroze
<https://github.com/sroze> : Actually you'll get a Could not denormalize
object of type \DateTime, no supporting normalizer found exception.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#25287 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ADSq8hmKipIiAjyAs1w9u9spR-fo2I07ks5s9SAcgaJpZM4Qzu3l>
.
|
IIRC: as a nullable nested attribute on an object when using the |
@ogizanagi I kind of agree with you, @dunglas WDYT ? |
233ad77
to
6bfb5a2
Compare
PR Modified to now throw on empty strings and null values. |
Why why does this normalizer lie in supportsDenormalization if it doesn't support null/empty string? |
Because if we add a test it will throw an invalid message.
Le dim. 10 déc. 2017 à 16:01, Gabriel Ostrolucký <notifications@github.com>
a écrit :
… Why why does this normalizer lie in supportsDenormalization if it doesn't
support null/empty string?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#25287 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ADSq8vCdjpPvAIwTUCFsyWSWTFq9J1XFks5s-_I8gaJpZM4Qzu3l>
.
|
It's kind of right, isn't it? It says no supporting denormalizer has been found, which is true. This denormalizer does not support null. That message could be improved, but that's different problem. |
None of the denormalizers supports null actually AFAIK. IMHO, it's confusing getting a "No denormalizer found" exception when explicitly asking for |
It is, but that's not a problem of this normalizer, that's a thing to be fixed in Serializer. If denormalizers are not allowed to decide if they support denormalization based on a value passed, that's serious flaw in DenormalizerInterface |
I suggest we return null for null input. It would be consistent with JMS serializer. |
@ostrolucky I don't know if we have to be consistent with JMS. I think returning an error is better for DX because you may have a bug at some point and passing null instead of the right value, this shows you that something is wrong. If you are returning null it could lead to unwanted behaviour since this should not be able to return null. I agree that something has to be done in the denormalizer (supports method) but this is IMO the best way to deal with this. |
Forcing developer to implement his own denormalizer just to return null for null input and messing with order of denormalizers in serializer is bad DX. It's also bad DX to work around the root problem (not fixing message in Serializer), so when developer implements supportsDenormalization with check based on value, he will get weird message again. How about this then: Allow to specify target of denormalization to be
We don't have to do it same way, but we should take more inspiration from it. JMS is much more mature PHP serializer. We don't have to throw exception and hope for the best that developers won't mind it too much. We can learn from history of others. Right now we are dealing with problems which were already solved long ago. We shouldn't have to do that. JMS datetime denormalizer returns null for null input since 2012. It also allows to specify what to do with nulls in scope of whole Serialization context, via Context setting. But that's outside the scope of this PR. For now my request is to at least give developer option to not crash denormalization if input in this denormalizer is null. Seems returning null is expected behaviour from user who posted linked issue too, after all. |
So @ogizanagi what do you think ? |
There might be a little misunderstanding here: no need for the developper to implement his own denormalizers just for handling High-level denormalizers like the ObjectNormalizer are clever enough to not call Low-level denormalizers in core like the DateTime ones never accounted for So to sum-up: I think this patch is fine regarding the current state of the serializer and core denormalizers. Handling |
@@ -67,6 +67,10 @@ public function denormalize($data, $class, $format = null, array $context = arra | |||
{ | |||
$dateTimeFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : null; | |||
|
|||
if ('' === $data || null === $data) { | |||
throw new UnexpectedValueException('The data is either an empty string or null, you should pass an object implementing \DateTimeInterface.'); |
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.
This message is wrong: we don't expect an object implementing \DateTimeInterface
. We expect a string that can be parsed according to the configured format or the \DateTime::__construct()
if not configured.
6bfb5a2
to
9bfbf3d
Compare
…turning null or empty instead of new object)
9bfbf3d
to
74726f3
Compare
Thank you @Simperfit. |
… values (returning it instead of new object) (Simperfit) This PR was merged into the 3.3 branch. Discussion ---------- [Serializer] DateTimeNormalizer handling of null and empty values (returning it instead of new object) | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no <!-- don't forget to update src/**/CHANGELOG.md files --> | BC breaks? | no | Deprecations? | no <!-- don't forget to update UPGRADE-*.md files --> | Tests pass? | no | Fixed tickets | #23964 | License | MIT | Doc PR | I'm openning the disucussion on this as I think that should be returning null and not a new object. WDYT ? Working at home ;)  Commits ------- 74726f3 [Serializer] DateTimeNormalizer handling of null and empty values (returning null or empty instead of new object)
With this feature we can't anymore denormalize object with null datetime attributes ? On this call:
I get this error : The null attribute is There isn't an option to skip null values ? |
I found a solution : php doc type hinting null too: /**
* @var DateTime|null
* @Assert\DateTime()
*/
private $updatedAt; |
@florianajir : As I said in a previous comment, the ObjectNormalizer is clever enough to not call |
I'm openning the disucussion on this as I think that should be returning null and not a new object.
WDYT ?
Working at home ;)
