我有一个非常简单的自定义 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
到底缺少什么?谢谢!
解决方案很简单,但 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 并且一切正常。