Skip to content

MapQueryString & MapRequestPayload empty when type missmatch #50904

Closed
@Grafikart

Description

@Grafikart

Symfony version(s) affected

6.3.1

Description

When there is a type missmatch on an objet with the attribute MapQueryString or MapRequestPayload an empty instance is created.

For instance if I use MapQueryString expecting a name (string) and age (int) but the user send a "John" and "foo", I end up with an empty object.

How to reproduce

  1. Create a simple DTO (I deliberately omitted NotBlank)
final readonly class PayloadDTO
{

    public function __construct(
        #[Assert\Length(min: 3)]
        public string $name,

        #[Assert\Positive]
        public int    $age
    )
    {
    }

}
  1. Map this DTO in a controller
class HomeController extends AbstractController
{
    #[Route('/', name: 'home')]
    public function index(
        #[MapQueryString] PayloadDTO $payload,
    ): Response
    {
        dd($payload); // I expect the dto to be valid (with an age / name property)
    }

}
  1. Try to access the page using an "age" that is not a number. http://localhost:8000/?name=John&age=foo, you'll end up with an empty PayloadDTO (which will cause bugs further down the application).

Possible Solution

I tracked down the issue to the AbstractNormalizer that ends up instantiating the object without using the constructor (using the reflectionClass) since there is a not_normalizable_value_exceptions in the context. https://github.com/symfony/symfony/blob/6.4/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php#L424-L428

A solution would be to check the context for "collect_denormalization_errors" before skipping the exception or to collect the exception when it happens.

            try {
                return $reflectionClass->newInstanceArgs($params);
            } catch (\TypeError $e) {
                if (!isset($context['not_normalizable_value_exceptions'])) {
                    throw $e;
                }

                $context['not_normalizable_value_exceptions'][] = NotNormalizableValueException::createForUnexpectedDataType(/* Find which parameters to give */);

                return $reflectionClass->newInstanceWithoutConstructor();
            }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions