[HttpKernel] Denormalize request data using the csv format when using "#[MapQueryString]" or "#[MapRequestPayload]" (except for content data) #59134
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This fixes the scenario mentioned above where using
#[MapQueryString]
or#[MapRequestPayload]
(except request content) with at least one readonly property with a type mismatch error leads to getting an object with uninitialized properties. The only properties that are set are the ones that are assigned a value via a request parameter and are NOT readonly. Moreover, if the corresponding query parameter is not provided for non-readonly property A and there is at least one other readonly property B that has a type mismatch then A will still be returned as uninitialized (even if it has a default value).Shortly put, the instantiation fails and the values of the properties cannot be set later on.
Examples
The complete list of steps to reproduce this is provided in #59104.
The reason why this happens is because we are disabling the type enforcement of the denormalizer in the
Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver
class and when we eventually end up in thevalidateAndDenormalize
method of theSymfony\Component\Serializer\Normalizer\AbstractObjectNormalizer
class we ignore the type mismatch because of:Thus, we get a type error when trying to create the object and we fall back to
$reflectionClass->newInstanceWithoutConstructor();
Then, based on the provided request data, we attempt to set the values of the properties but this process fails for the readonly properties so they stay uninitialized.
As discussed with @nicolas-grekas during the hackathon at SymfonyCon Vienna 2024 the solution here is to stop disabling the type enforcement of the denormalizer. However, this alone is not enough because then we won't be able to use anything but string since this is the type that comes in the request so we also need to set the denormalization format to either
csv
orxml
.This comment from
the Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer
sheds some light on why:We avoid
xml
due to some special formatting that occurs so the proposed solution usescsv
.Basically, we start using type enforcement + csv format where non-string values are transformed.