core icon indicating copy to clipboard operation
core copied to clipboard

Input DTO unable to deserialize ID for updates.

Open jonnyeom opened this issue 1 year ago • 1 comments

API Platform version(s) affected: 3.2.x ?+

Description
When updating a resource while using a DTO as an input, (and not using the DTO as the direct resource), Serializer does not deserialize the ID onto the DTO.

How to reproduce
Here is a sample situation with an Entity, an Input DTO, and a Processor to reveal missing ID.

// The Entity class.
#[ApiResource(
    operations: [
        new Patch(
            ...
            uriTemplate: '/api/entity/{id}',
            input: EntityInput::class,
            processor: EntityProcessor::class
        ),
    ],
)]
class Entity
{
    #[ORM\Id]
    #[ORM\Column(type: 'uuid', unique: true)]
    #[ApiProperty(identifier: true)]
    private Uuid $id;

    ...
}


// The DTO class.
class EntityInput 
{    
    public ?Uuid $id = null;

    // Whatever data to be sent.
    public string $date;
    public array $information;
    ...
}

// The API Request.
->PATCH({
    '/api/entity/{123456}',
    {
        date: 01-01-2024
        information: [
            'important',
            'data',
        ]
    }
})

// The Processor.
class EntityProcessor 
{    
    /**
     * @param EntityInput $data
     */
    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []) {
        \assert $data instanceof EntityInput; // True !
        $data->getId(); // null ?? 
    }
}

Here, I was expecting 123456 to be id. I know the ID is available. If you hook into the deserializer, $context[ObjectNormalizer::OBJECT_TO_POPULATE] contains the Original Entity to be updated (not at the processor level however). and the identifier is extracted correctly every time. This works as expected when the DTO is the Resource itself. Shouldnt it work the other way around?

Possible Solution
SO im guessing its one of 2 things.

  1. IDs are only deserialized onto DTOs if the DTO is the ApiResource itself If so, I think this should be documented and the DTO example in documentation should stop using input:
  2. (Its a bug) IDs should be deserialized, but its not working when used as input: class.
  3. I mis-attributed by entity classes altogether. everything should work fine.

jonnyeom avatar Apr 04 '24 16:04 jonnyeom

Try use different Uuid version, in one of my projects only using UuidV1/V4 worked for both api-platform x doctrine

karrakoliko avatar Apr 14 '24 15:04 karrakoliko

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 14 '24 01:06 stale[bot]