Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Serializer] add return types#42512

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@nicolas-grekas
Copy link
Member

QA
Branch?6.0
Bug fix?no
New feature?yes
Deprecations?no
Tickets#40154
LicenseMIT
Doc PR-

Extracted from#42496

Not all possible return types are patched for the attached components, to save breaking BC cross-components, for now at least.

Serializer's test fails. Help wanted 🙏

@carsonbot
Copy link

Hey!

I think@VincentLanglet has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@chalasr
Copy link
Member

ping@lyrixx as the failing tests seem related to your recent addition

@lyrixx
Copy link
Member

lyrixx commentedAug 13, 2021
edited
Loading

I noticed that when I added tests. There is a bug IMHO in the serializer, but if we fix it, it would be a BC break. So I let everything in place.


Reproducer with symfony4.4.29 (yeah, branch 4.X to be sure it's "old")

$serializer =newSymfony\Component\Serializer\Serializer(    [newSymfony\Component\Serializer\Normalizer\ObjectNormalizer(),newSymfony\Component\Serializer\Normalizer\ArrayDenormalizer(),    ],    ['json' =>newSymfony\Component\Serializer\Encoder\JsonEncoder(),    ]);class DummyListimplements \Countable, \IteratorAggregate{public$list;publicfunction__construct(array$list)    {$this->list =$list;    }publicfunctioncount():int    {return\count($this->list);    }publicfunctiongetIterator():\Traversable    {returnnew \ArrayIterator($this->list);    }}var_dump($serializer->serialize(newDummyList([]),'json', [Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS =>true,]));var_dump($serializer->serialize(newDummyList(range('a','d')),'json', [Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS =>true,]));

=>

string(11) "{"list":[]}"string(17) "["a","b","c","d"]"

As you can see, this is (IMHO) wrong.
The shape is not the same when the collection is empty or not! it should be{} in the first example.

And to be 100% sure, with normalize instead of serialize:

object(DummyList)#15 (1) {  ["list"]=>  array(0) {  }}array(4) {  [0]=>  string(1) "a"  [1]=>  string(1) "b"  [2]=>  string(1) "c"  [3]=>  string(1) "d"}

TL;DR: I did not broke anything (👼🏼) because I did not want to break the BC when I found this bug.
And the bug (highlighted by this PR) exists for ages.

I don't know what is the best way to deal with this :/ I can fix the bug if you want... (super easy)


ping@Foxprodev

@Foxprodev
Copy link
Contributor

Foxprodev commentedAug 14, 2021
edited
Loading

@lyrixx You are right.
But countable is not always traversable like traversable is not always countable. I think that's whyPRESERVE_EMPTY_OBJECTS just keeps object with count = 0. Nvm, I've checked the serializer code and there is is_iterable check too.
Latest PR does not change old behavior, that mixed return came fromPRESERVE_EMPTY_OBJECTS support
On the other side PHP does not support generic types and overloading so if we returningmixed $data the returning type unfortunately should bemixed

@Foxprodev
Copy link
Contributor

Foxprodev commentedAug 14, 2021
edited
Loading

I have a suggestion. Can we makeArrayObject (orstdClass) a normal form of non-traversable objects? I am sure that serializer should work with "normal forms" only. And the returing types is the list of "normal forms"
Not the best idea :)
Maybe the better idea is to remove this case in 6.0

switch (true) {
case ($context[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS] ??false) &&\is_object($data):
return$data;

and returnstdClass when data array is empty (additionally it is 8+ times faster than ArrayObject)
if (isset($context[self::PRESERVE_EMPTY_OBJECTS]) && !\count($data)) {
returnnew \ArrayObject();
}

Yes.

I will open PR if you like this option

P.S. Currently in one of my projects I have normalizer, which just returns object as it is (for performance tuning). So it's possible only with mixed return type.
I am still sure return type should be mixed or maybe the better OOP approach to return wrapper class likeNormalizedElement, which can also contain additional meta for serializing (like the target type in json) and can be JsonSerializable. Not sure about another formats but meta is always useful

@dunglas
Copy link
Member

@lyrixx AFAIK custom collection structures have never been supported and lead to undefined behaviors (as showed by your test). Only native collection structures are currently well-supported (array andArrayObject IIRC). Supporting custom structures would be better, but IMHO it's a new feature and there are probably many other weird behaviors like the one you pointed out to support.

@Foxprodev I agree that returning a structure containing the normalized/serialized data and the related metadata would be useful, we also need such metadata for API Platform (for instance to store the identifiers of serialized resources to generated cache tags, or to generate various HTTP headers). However, I fear that it's a huge change that would be made at the same time as the planned Serializer refactoring (having only 1 object normalizer using PropertyInfo and PropertyAccess under the hood etc):#30818

@nicolas-grekas
Copy link
MemberAuthor

PR welcome to fix the issue@lyrixx
Branch 5.4 with a deprecation if possible, just in case.

@nicolas-grekasnicolas-grekasforce-pushed thereturn-types-ser branch 2 times, most recently from9f724ca to9b22a45CompareAugust 17, 2021 15:44
@lyrixx
Copy link
Member

Okay I'll do that

@lyrixx
Copy link
Member

@nicolas-grekas see#42619. I'll open a PR on 6.0 once merged to really fix the bug

@Foxprodev
Copy link
Contributor

@dunglas So thearray|string|int|float|bool|\ArrayObject|null returning type inNormalizerInterface is the final decision?

@dunglas
Copy link
Member

dunglas commentedAug 18, 2021
edited
Loading

I would keepmixed for now to be honest. And I'm totally in favor of the new class giving access to metadata if there is an upgrade path (and I think that it's doable).

chalasr and Foxprodev reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedAug 18, 2021
edited
Loading

It's possible to widen, but it's going to be very hard to tighten without causing a BC break. Better start with narrow types.

@nicolas-grekas
Copy link
MemberAuthor

PR is green, remaining failures are false positives.

@nicolas-grekasnicolas-grekas merged commit4780f05 intosymfony:6.0Aug 19, 2021
@nicolas-grekasnicolas-grekas deleted the return-types-ser branchAugust 19, 2021 08:57
@nicolas-grekas
Copy link
MemberAuthor

(merging because if there is any discussion to have on return types, it should be done on 5.4)

dunglas reacted with thumbs up emoji

@thrashzone13
Copy link

@nicolas-grekas return type of serializer method isn't always string. It can be array if array is passed as format param.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@dunglasdunglasdunglas approved these changes

Assignees

No one assigned

Projects

None yet

Milestone

6.0

Development

Successfully merging this pull request may close these issues.

7 participants

@nicolas-grekas@carsonbot@chalasr@lyrixx@Foxprodev@dunglas@thrashzone13

[8]ページ先頭

©2009-2025 Movatter.jp