Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpKernel] Create #[Serialize] Attribute to serialize Controller Result #49518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 7.4
Choose a base branch
from

Conversation

Koc
Copy link
Contributor

@Koc Koc commented Feb 23, 2023

Q A
Branch? 6.3
Bug fix? no
New feature? yes
Deprecations? no
Tickets -
License MIT
Doc PR TBD

#[Serialize(code: 200, headers: [], serializationContext: [])] Allows automatically serialize Controller Result to format based on Request format.

Usage example 🔨

class Product
{
    public function __construct(public readonly int $id, public readonly string $name)
    {
    }
}

class GetProductController
{
    #[Serialize]
    public function __invoke(): Product
    {
        return new Product(1, 'Asus UX550');
    }
}

class ProductCreated
{
    public function __construct(public readonly int $id)
    {
    }
}

class CreateProductController
{
    #[Serialize(201)]
    public function __invoke(): ProductCreated
    {
        return new ProductCreated(1);
    }
}

# same controller without annotation: repeatable annoying boilerplate which has no sense to write
class CreateProductControllerLegacy
{
    public function __construct(private readonly SerializerInterface $serializer)
    {
    }

    #[OA\Response(response: 201, description: 'Successful response', content: new Model(type: ProductCreated::class))]
    public function __invoke(): JsonResponse
    {
        $data = new ProductCreated(1);
        $serialized = $this->serializer->serialize($data, 'json');

        return JsonResponse::fromJsonString($serialized, JsonResponse::HTTP_CREATED);
    }
}

Todo

@Koc Koc changed the title Create #[SerializedResponse] Attribute to serialize Controller Result [HttpKernel] Create #[SerializedResponse] Attribute to serialize Controller Result Feb 23, 2023
@Koc Koc force-pushed the feature/serialized-response branch from 8e54594 to 9e16d8c Compare February 23, 2023 22:36
ro0NL

This comment was marked as outdated.

@Koc Koc force-pushed the feature/serialized-response branch from a30ee49 to 06087b9 Compare February 24, 2023 11:41
@Koc Koc changed the title [HttpKernel] Create #[SerializedResponse] Attribute to serialize Controller Result [HttpKernel] Create #[Serialized] Attribute to serialize Controller Result Feb 24, 2023
@Koc Koc changed the title [HttpKernel] Create #[Serialized] Attribute to serialize Controller Result [HttpKernel] Create #[Serialize] Attribute to serialize Controller Result Feb 24, 2023
* Controller tag to serialize response.
*/
#[\Attribute(\Attribute::TARGET_METHOD)]
class Serialize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, others attribute are prefixed with As when they describe more the config of the class (AsCommand or AsMessageHandler)
here it is like a mapping/transformation, perhaps like your other PR #49138 MapResponse

@Koc Koc force-pushed the feature/serialized-response branch 2 times, most recently from 9eea8e6 to 9d1fb32 Compare February 25, 2023 22:13
@yceruto
Copy link
Member

yceruto commented Feb 27, 2023

This test is failing https://github.com/symfony/symfony/actions/runs/4272061115/jobs/7436960556#step:7:8239

You probably have to add symfony/serializer as a dev dependency of the http-kernel component.

@Koc
Copy link
Contributor Author

Koc commented Feb 27, 2023

yes, thanx, it was added in #49138. I've not added it here to prevent merge conflicts. Also I want extend functional tests added in mentioned PR with new Attribute

@Koc Koc force-pushed the feature/serialized-response branch from 9d1fb32 to 3213f4b Compare March 6, 2023 22:16
@Koc Koc requested a review from dunglas as a code owner March 6, 2023 22:16
@Koc Koc force-pushed the feature/serialized-response branch 2 times, most recently from fbc4eae to ca0b60d Compare March 6, 2023 22:30
ro0NL

This comment was marked as outdated.

@Koc Koc force-pushed the feature/serialized-response branch 2 times, most recently from 9845ae5 to f350273 Compare April 6, 2023 22:22
@nicolas-grekas
Copy link
Member

nicolas-grekas commented Apr 7, 2023

For what it's worth, I'm personally not convinced we should merge this. The reason is that the resulting behavior is very limited and resorting to explicit code comes very quickly - as soon as one needs more precise control over the resulting response for example. In the end, this saves two/three lines that are legit to have in a controller/similar to me.

@Koc
Copy link
Contributor Author

Koc commented Apr 7, 2023

Exactly, this can save few lines in the Controller and reduce boilerplate. Of course it can't cover all needs for an every project, but same applicable for other stuff provided by Framework. 80/20 rule in action. We have few microservices that uses only #[Serialize] Attribute without any kind of additional control for the Response.

We can go further and build OpenApi documentation based on Controller return type + Attribute existence via NelmioApiDocBundle. It will reduce even more boilerplate code for some projects.

@Koc Koc force-pushed the feature/serialized-response branch 4 times, most recently from 8ee1da3 to 9058a4b Compare April 21, 2023 07:38
@Koc Koc force-pushed the feature/serialized-response branch from 9058a4b to ad86cea Compare April 22, 2023 10:40
@Koc
Copy link
Contributor Author

Koc commented Apr 22, 2023

Rebased, renamed context to serializationContext for consistency for Map* attributes. Test failures looks unrelated.

@nicolas-grekas please review 🙏

@nicolas-grekas nicolas-grekas modified the milestones: 6.3, 6.4 May 23, 2023
@nicolas-grekas nicolas-grekas modified the milestones: 6.4, 7.1 Nov 15, 2023
@Koc Koc force-pushed the feature/serialized-response branch from ad86cea to 3c9a9b6 Compare January 29, 2024 16:15
@Koc Koc force-pushed the feature/serialized-response branch from 3c9a9b6 to 490a4ad Compare January 29, 2024 16:23
@Koc
Copy link
Contributor Author

Koc commented Jan 29, 2024

I've rebased PR one more time + fixed tests + actualized changelog.

And as I've already mentioned - this feature needed not only for reducing boilerplate of serialization but also for simplification of the OpenApi spec generation via NelmioApiDocBundle. They already successfully adopted #[MapRequestPayload/MapQueryString]. So, introduction of this attribute can be a good step forward in same direction.

* @author Konstantin Myakshin <[email protected]>
*/
#[\Attribute(\Attribute::TARGET_METHOD)]
final class Serialize
Copy link

@DavidGarciaCat DavidGarciaCat Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this #[Serialize] attribute allow to pass the groups to be used during the serialization process?

Also, the SerializerInterface and its serialize method allows us to pass the preferred format (JSON, XML, ...) so making it an argument (even with a predefined value) makes sense to me 🤔

==== EDIT ====

By the way: with "passing groups" I meant that they seem to be a relevant setting so maybe it's a good idea to add them with a shortcut (instead of passing them via context), but that's just a secondary matter - the primary concern here is the missing format:

$data = $this->serializer->serialize(
            data: $output,
            format: 'json',
            context: ['groups' => ['Group1', 'Group2']]
        );

so it could be like this:

#[Serialize(code: 201, format: 'json', headers: [], serializationContext: ['groups' => ['Group1', 'Group2']])]

or even

#[Serialize(code: 201, format: 'json', headers: [], groups: ['Group1', 'Group2'])]

@xabbuh xabbuh modified the milestones: 7.1, 7.2 May 15, 2024
* @author Konstantin Myakshin <[email protected]>
*/
#[\Attribute(\Attribute::TARGET_METHOD)]
final class Serialize
Copy link

@rrajkomar rrajkomar Nov 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
I think this is a great idea and would be very useful for anyone developing webservice so thank you.
However wouldn't it be more logical for consistency to name the attribute in the same manner as the others ?
Something like MapResponsePayload seems more intuitive IMHO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this attributes can be renamed soon, see #58709

@fabpot fabpot modified the milestones: 7.2, 7.3 Nov 20, 2024
@fabpot fabpot modified the milestones: 7.3, 7.4 May 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.