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]default_constructor_arguments context option for denormalization#25493

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

Conversation

@Nek-
Copy link
Contributor

@Nek-Nek- commentedDec 14, 2017
edited
Loading

QA
Branch?master
Bug fix?no
New feature?yes
BC breaks?no
Deprecations?no
Tests pass?yes
Fixed tickets(there is no RFC for this)
LicenseMIT
Doc PRsymfony/symfony-docs#8914

Problems

In the case you want to deserialize value-objects, if all the data required by its constructor arenot given as input, the serializer will throw a simpleRuntimeException exception. This makes impossible to catch it. (as current fix on my projects I use exception message to be sure to catch the good one X.x")

The second problem is a missing feature to fill the required object with an empty one. This needs to be defined by the user because the serializer can't guess how to build it.

Here is a project that exposes the problem of the current behavior.https://github.com/Nek-/api-platform-value-object

Solutions suggested

I suggest a solution in 2 parts because the second part is more touchy.

  1. Replace the current exception by a new specific one
  2. Add a newempty_data option to the context of deserialization so you can specify data for objects impossible to instantiate, this is great because the serializer no more throw exception and the validator can then work as expected and send violations to the user. This solution is inspired by forms solutions to fix the issue with value objects

Here is what you can do with this feature:

class DummyValueObject{publicfunction__construct($foo,$bar) { $this->foo =$foo;$this->bar =$bar; }}$empty =newDummyValueObject('','');$result =$normalizer->denormalize(['foo' =>'Hello'], DummyValueObject::class,'json', ['empty_data' => [        DummyValueObject::class =>$empty,    ],]);// It's impossible to construct a DummyValueObject with only "foo" value. So the serializer// will replace it with the given empty data

There are 2 commits so I can quickly provide you only the first point if you want. Hope you'll like this.

Solution after discussion

  1. New exceptionMissingConstructorArgumentsException
  2. New context optiondefault_constructor_arguments
class DummyValueObject{publicfunction__construct($foo,$bar) { $this->foo =$foo;$this->bar =$bar; }}$result =$normalizer->denormalize(['foo' =>'Hello'], DummyValueObject::class,'json', ['default_constructor_arguments' => [        DummyValueObject::class => ['foo' =>'','bar' =>''],    ],]);// DummyValueObject is contructed with the given `foo` and empty `bar`

pimolo reacted with thumbs up emoji
@Nek-Nek- changed the titleFeature/empty data for denormalization[Serializer]empty_data context option for denormalizationDec 14, 2017
@Nek-Nek-force-pushed thefeature/empty-data-for-denormalization branch 2 times, most recently from6146b67 tod305b76CompareDecember 14, 2017 13:33
@nicolas-grekasnicolas-grekas added this to the4.1 milestoneDec 18, 2017
namespaceSymfony\Component\Serializer\Exception;

/**
* IncompleteInputDataException.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Can you give a more explicit description or just remove this line?

Copy link
ContributorAuthor

@Nek-Nek-Dec 20, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It's inspired by (almost) all other exceptions already present. Are you sure?

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Serializer/Exception/RuntimeException.php#L15

$params[] =$constructorParameter->getDefaultValue();
}else {
thrownewRuntimeException(
if (isset($context[static::EMPTY_DATA][$class])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Shouldn't we check if$class is an instance of the key usingis_a (I've no strong opinion about that).

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

With the new way of managing empty data; this is not accurate anymore.

'foo' =>10,
);

$this->expectException(\Symfony\Component\Serializer\Exception\IncompleteInputDataException::class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Prefer using@expectedException and@expectedExceptionMessage instead.


$normalizer =newObjectNormalizer();
$serializer =newSerializer(array($normalizer));
$normalizer->setSerializer($serializer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This line is useless,Serializer will inject itself.


$normalizer =newObjectNormalizer();
$serializer =newSerializer(array($normalizer));
$normalizer->setSerializer($serializer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Same.

@dunglas
Copy link
Member

In your example, thefoo value is lost. Shouldn't we provide defaults for each constructor parameter instead (like we can do in the DI component to build services)? It will allow to only fill the missing parameters instead of discarding all data provided by the using.

Nek- reacted with thumbs up emoji

@Nek-Nek-force-pushed thefeature/empty-data-for-denormalization branch 3 times, most recently froma5c2a5e todf432b9CompareDecember 20, 2017 19:43
@Nek-
Copy link
ContributorAuthor

@dunglas updated following your advice :).

// Don't run set for a parameter passed to the constructor
$params[] =$parameterData;
unset($data[$key]);
}elseif ($allowed && !$ignored &&isset($context[static::EMPTY_DATA][$class][$key])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I would not check for$allowed && !$ignored, because this data is provided by the developer, not by the end user.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It can lead to weird behaviors but I'm in favor of given more power to the developer too. 👍

@Nek-Nek-force-pushed thefeature/empty-data-for-denormalization branch fromdf432b9 to4ae704aCompareDecember 21, 2017 08:42
@Nek-
Copy link
ContributorAuthor

Nek- commentedDec 21, 2017
edited
Loading

@dunglas this is good now :).

@Nek-
Copy link
ContributorAuthor

Status: Needs Review

@Nek-
Copy link
ContributorAuthor

Nek- commentedJan 8, 2018

ping@dunglas 😄

-----

* added`IncompleteInputDataException` new exception for deserialization failure
of objects that needs data insertion in constructor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Is it only when the constructor requires specific arguments? If yes then something likeMissingConstructorArgumentsException would make more sense. If not, then it needs to be clarified here :)


* added`IncompleteInputDataException` new exception for deserialization failure
of objects that needs data insertion in constructor
* added an optional`empty_data` option of context to specify a default data in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Same reflection... what aboutdefault_constructor_arguments ?

Copy link
Member

@dunglasdunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

(when wording issues in the changelog will be resolved)

Before: impossible to catch value object hydratation failureAfter: catch the new exceptionNo BC break.
@Nek-Nek-force-pushed thefeature/empty-data-for-denormalization branch from4ae704a to7cf8514CompareJanuary 15, 2018 06:43
@Nek-
Copy link
ContributorAuthor

@sroze that's absolutely relevant. I made the naming changes. 👍

@Nek-Nek- changed the title[Serializer]empty_data context option for denormalization[Serializer]default_constructor_arguments context option for denormalizationJan 15, 2018
constGROUPS ='groups';
constATTRIBUTES ='attributes';
constALLOW_EXTRA_ATTRIBUTES ='allow_extra_attributes';
constEMPTY_DATA ='default_constructor_arguments';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Might as well rename theEMPTY_DATA constant then :)

Copy link
ContributorAuthor

@Nek-Nek-Jan 15, 2018
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Arg! Fixed.

You can now add empty_data to the context on deserializationof objects. This allow you to deserialize objects that haverequirements in the constructor that can't be given.Basically, it helps you hydrate with value objects, so thevalidation component can invalid the object without theserializer send an error.
@Nek-Nek-force-pushed thefeature/empty-data-for-denormalization branch from7cf8514 to7b8b165CompareJanuary 15, 2018 14:40
Copy link
Contributor

@srozesroze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

👌

@Taluu
Copy link
Contributor

Supporting a callback in the option with the data could help to instantiate value object or entity objects with required params that can't be set to their default value could be awesome.

Nek- reacted with thumbs up emoji

@fabpot
Copy link
Member

Thank you@Nek-.

@Nek-Nek- deleted the feature/empty-data-for-denormalization branchJanuary 19, 2018 22:41
@fabpotfabpot mentioned this pull requestMay 7, 2018
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull requestJun 27, 2018
…uiluz)This PR was merged into the 4.1 branch.Discussion----------Add new serializer empty_data feature docThis is the documentation related to the following feature:symfony/symfony#25493Commits-------9f31bbb Fix not precise enough sentenceb0d3fe8 Minor reword5a48201 Add new serializer empty_data feature doc
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@dunglasdunglasdunglas approved these changes

+2 more reviewers

@TaluuTaluuTaluu approved these changes

@srozesrozesroze approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

4.1

Development

Successfully merging this pull request may close these issues.

8 participants

@Nek-@dunglas@Taluu@fabpot@sroze@javiereguiluz@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp