API Platform Serialization issue for custom Output

I have created this resource in order to request a password reset token:

POST {{api_base_url}}/users/password/reset-request

Payload example 
{
    "email" :"[email protected]"
}

Everything works fine but the response doesn’t serialize ResetPasswordRequestOutput to show the result. I got this response instead (as User type)

{
"@context": {
    "@vocab": "http://dev.api.xxxxxxxxxx.com/docs.jsonld#",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "token": "ResetPasswordRequestOutput/token"
},
"@type": "User",
"@id": "/users/00000000-0000-0000-0000-000000000002",
"token": "ORGOsGh01sr8R91J"
}

Exepected output: (of type: ResetPasswordRequestOutput)

{
"@type": "ResetPasswordRequestOutput",
"token": "ORGOsGh01sr8R91J"
}

Code:

The controller class of the custom operation:

final class  ResetPasswordRequest {

private $validator;

private $entityManager;

public function __construct(ValidatorInterface $validator, EntityManagerInterface $entityManager)
{
    $this->entityManager = $entityManager;
    $this->validator = $validator;
}

public function __invoke(ResetPasswordRequestInput $data)
{
    $this->validator->validate($data);

    $userRepository = $this->entityManager->getRepository(User::class);

    /** @var User $user */
    $user = $userRepository->findOneBy(['email' => $data->email]);
    if (!$user) {
        throw new ItemNotFoundException("invalid token");
    }
    if ($user->getStatus() !== UserStatus::ACTIVE) {
        throw new AccessDeniedException("user is inactive");
    }

    $generator = (new Factory())->getGenerator(new Strength(Strength::MEDIUM));
    $token = $generator->generateString(16, 'BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
    $user->setToken($token);

    return $user;
}
}

The data transofrmer that converts User object to ResetPasswordRequestOutput

 namespace AppDataTransformer;
    final class ResetPasswordRequestOutputDataTransformer implements DataTransformerInterface
    {

        private $normalizer;

        public function __construct(NormalizerInterface $normalizer)
        {
            $this->normalizer = $normalizer;
        }

        /**
         * {@inheritdoc}
         */
        public function transform($data, string $to, array $context = [])
        {
            $output = new ResetPasswordRequestOutput();
            $output->token = $data->getToken();

            return $output;
        }

        /**
         * {@inheritdoc}
         */
        public function supportsTransformation($data, string $to, array $context = []): bool
        {
            return ResetPasswordRequestOutput::class === $to && $data instanceof User;
        }

DTO object that holds input data

<?php

namespace AppDto;



final class ResetPasswordRequestInput
{
    /**
     * @var string
     *
     * @AssertEmail
     * @Groups({"user:write"})
     */
    public $email;

}

DTO object that holds output data

namespace AppDto;

final class ResetPasswordRequestOutput
{
    /**
     * @var string
     *
     * @AssertNotNull()
     * @Groups({"user:read"})
     */
    public $token;

}

User Entity class with ApiResource annotation (partial) action=reset_password_request

/**
 * @ApiResource(
 *     normalizationContext={"groups"={"user", "user:read"}},
 *     denormalizationContext={"groups"={"user", "user:write"}},
 *     collectionOperations={
 *        "get",
 *        "post",
 *        "reset_password_request" = {
 *              "method"= "POST",
 *              "read"=false,
 *              "path"="/users/password/reset-request",
 *              "controller"=ResetPasswordRequest::class,
 *              "status"=200,
 *              "input"=ResetPasswordRequestInput::class,
 *              "output"=ResetPasswordRequestOutput::class,
 *              "normalization_context"={"jsonld_embed_context"=false}
 *         },

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *