API平台自定义Controller序列化问题

问题描述 投票:0回答:1

我有一个非常简单的自定义 API 端点,带有输入和输出 DTO 以及 Symfony 控制器,按照文档页面中的示例进行构建:https://api-platform.com/docs/v2.3/core/dto/

#[AsController]
class MessageDataGetInvokeController extends AbstractController
{
    #[Route(
        path: '/api/messages',
        name: 'messages_get_invoke',
        defaults: [
            '_api_respond' => true,
            '_api_normalization_context' => ['api_sub_level' => true]
        ],
        methods: ['GET']
    )]
    public function __invoke(
        #[MapQueryString] MessageReadInputDto $messageReadInputDto
    ): MessageReadOutputDto {
        return new MessageReadOutputDto(
            data: 'test invoke controller: ' . $messageReadInputDto->getBusinessKey()
        );
    }
}

readonly class MessageReadInputDto
{
    public function __construct(
        #[Groups(['custom:read'])]
        #[ApiProperty(example: 'b19d262e-ad00-4c57-8a4d-dbcbe294da8e')]
        public string $businessKey
    ) {
    }

    public function getBusinessKey(): string
    {
        return $this->businessKey;
    }
}

readonly class MessageReadOutputDto
{
    public function __construct(
        #[Groups(['custom:read'])]
        public string $data
    ) {
    }

    public function getData(): string
    {
        return $this->data;
    }
}

#[ApiResource(
    operations: [
        new Get(
            output: MessageReadOutputDto::class,
            openapiContext: [
                'summary' => 'Retrieve messages',
                'description' => 'This endpoint retrieves a message by given input data',
                'parameters' => [
                    [
                        'name'        => 'businessKey',
                        'in'          => 'query',
                        'description' => 'Business process identifier',
                        'required'    => true,
                        'type'        => 'string',
                        'default'     => '',
                    ],
                ],
            ],
            routeName: 'messages_get_invoke',
            normalizationContext: ['groups' => ['custom:read']],
            read: false
        ),
        new Post(),
        new Put(),
        new Delete()
    ],
    normalizationContext: ['groups' => ['custom:read']],
    denormalizationContext: ['groups' => ['custom:write']],
)]
class Message
{
}

当我调用端点时,我收到此错误:

{
  "@id": "/api/errors",
  "@type": "hydra:Error",
  "title": "An error occurred",
  "detail": "Call to a member function serialize() on null",
  "status": 500,
  "type": "/errors/500",
  "trace": [
    {
      "file": "/var/www/html/vendor/api-platform/core/src/Symfony/EventListener/SerializeListener.php",
      "line": 133,
      "function": "serializeRawData",
      "class": "ApiPlatform\\Symfony\\EventListener\\SerializeListener",
      "type": "->"
    },
    {
      "file": "/var/www/html/vendor/symfony/event-dispatcher/Debug/WrappedListener.php",
      "line": 115,
      "function": "onKernelView",
      "class": "ApiPlatform\\Symfony\\EventListener\\SerializeListener",
      "type": "->"
    },

我的 API 平台配置:

api_platform:
    title: Hello API Platform
    version: 1.0.0
    use_symfony_listeners: true
    formats:
        jsonld: ['application/ld+json']
        json: ['application/json']
    docs_formats:
        jsonld: ['application/ld+json']
        jsonopenapi: ['application/vnd.openapi+json']
        html: ['text/html']
    defaults:
        rfc_7807_compliant_errors: true
        stateless: true
        cache_headers:
            vary: ['Content-Type', 'Authorization', 'Origin']
        extra_properties:
            standard_put: true
            rfc_7807_compliant_errors: true
    event_listeners_backward_compatibility_layer: false
    keep_legacy_inflector: false

到底缺少什么?谢谢!

symfony dto api-platform.com api-platform
1个回答
0
投票

解决方案很简单,但 API 平台文档中的记录确实不太好。如果API平台的人读到了这篇文章,请进行更新。

问题是,Ressource 类不可见,这就是没有序列化器的原因。要解决此问题,您必须以这种方式添加 Ressource 类:

#[AsController]
class MessageDataGetInvokeController extends AbstractController
{
    #[Route(
        path: '/api/messages',
        name: 'messages_get',
        defaults: [
            '_api_respond' => true,
            '_api_resource_class' => Message::class,
        ],
        methods: ['GET']
    )]
    public function __invoke(
        #[MapQueryString] MessageReadInputDto $messageReadInputDto
    ): MessageReadOutputDto {
        return new MessageReadOutputDto(
            data: 'test invoke controller: ' . $messageReadInputDto->getBusinessKey()
        );
    }
}

通过这种方式,序列化器处理返回的 DTO 并且一切正常。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.