Skip to content

feat(object-mapper): Honor the output class in ObjectMapperOutputProcessor on write operations#8420

Open
dylan-rumble wants to merge 1 commit into
api-platform:4.3from
dylan-rumble:feat/object-mapper-support-custom-output-dto
Open

feat(object-mapper): Honor the output class in ObjectMapperOutputProcessor on write operations#8420
dylan-rumble wants to merge 1 commit into
api-platform:4.3from
dylan-rumble:feat/object-mapper-support-custom-output-dto

Conversation

@dylan-rumble

Copy link
Copy Markdown
Q A
Branch? 4.3
License MIT
Doc PR api-platform/docs#...

Problem

When using the Symfony ObjectMapper integration ( stateOptions: new Options(entityClass: MyEntity::class) ), the read side and write side are inconsistent in how they resolve the target class.

On the read side,  ObjectMapperProvider correctly respects a configured  output  class, falling back to the operation class:

// src/State/Provider/ObjectMapperProvider.php
$data = $this->objectMapper->map($data, $operation->getOutput()['class'] ?? $operation->getClass());

On the write side,  ObjectMapperOutputProcessor ignores the output class entirely and always maps back to $operation->getClass() :

// src/State/Processor/ObjectMapperOutputProcessor.php
$dto = $this->objectMapper->map($data, $operation->getClass());

As a result, a write operation (POST / PATCH / PUT) that declares a dedicated output class silently maps the persisted entity back to the resource class instead of the requested output DTO. There is no way to return a different representation from a write than from a read when using ObjectMapper.

This is particularly limiting when the resource class itself cannot serve as a valid output representation for writes (for example, when the resource's IRI cannot be generated from the write result), forcing users to fall back to output: false and losing the response body altogether.

Fix

Mirror the read side so the processor honors the operation's output class when one is defined, falling back to the operation class otherwise:

$dto = $this->objectMapper->map($data, $operation->getOutput()['class'] ?? $operation->getClass());

This makes read and write paths symmetric and lets a write operation return a dedicated output DTO via ObjectMapper.

Backward compatibility

Fully backward compatible: when no output class is configured, getOutput() is null and behavior is unchanged (maps to $operation->getClass()).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant