Search code examples
phpsymfonysymfony6

DateTime deserialization in Symfony


I am trying to deserialize a JSON object in an API endpoint, but I am running to some problems.

I am using the #[MapRequestPayload] attribute and default SerializerInterface implementation. Running Symfony 6.4

The code is as follows:

UserController endpoint

    #[Route('/{id}', name: 'update', methods: ['PUT'])]
    #[IsGranted(UserVoter::EDIT, subject: 'user')]
    public function updateUser(
        #[MapEntity] User $user,
        #[MapRequestPayload] UserRequest $userRequest,
    ): JsonResponse {
        dd($userRequest);
        $this->userService->updateUserByRequest($user, $userRequest);
        return $this->json(
            new UserResponse($user)
        );
    }

DTO UserRequest

readonly final class UserRequest
{
    // Assert validation truncated
    public string $firstName;

    public string $lastName;

    public ?bool $wishBirthday;

    public ?\DateTimeImmutable $birthday;

    public ?UserRole $role;
}

The problem is that the birthday and role are not deserialized correctly, when sent in a request.

When I send this JSON, I get the 422 ValidationFailedException: This value should be of type unknown.. It does not even get to that dd call in the controller.

{
    "firstName": "Jan",
    "lastName": "Mrázek",
    "wishBirthday": false,
    "birthDay": "2020-01-06"
}

My question is - what exactly is going on in here? I don't suppose this is caused by #[MapRequestPayload] directly, but I suspect that the Serializer and my settings are to blame.


Solution

  • As I was trying to resolve this issue, I created a new project and tried a minimal example, similar to the one in question (controller with DTO mapped by #[MapRequestPayload] containing backed enum and date). However the example was working fine, so I tried the following in the real project:

    1. composer require symfony/serializer-pack - this, for some reason, installed 1 package, but only the content-hash changed in my composer.lock file
    2. Removed property_info: ~ from framework.yaml

    And after a full restart of symfony server, it started working. Hope this helps some lost soul, that encounters the same problem.