Calling GraphQL DeleteMutation ignores serialization groups and causes error
API Plaform: v3.3
Description:
Calling
mutation {
deleteGreeting(input: {id: "/api/greetings/cd"}) {
greeting {
id
_id
name
}
clientMutationId
}
}
produces
"debugMessage": "Cannot return null for non-nullable field \"Greeting.name\".",
"file": "/mnt/c/work/ap-gql-bug/my-api/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
while name is defined as non-nullable.
Expected behavior:
An output like this:
{
"data": {
"greeting": {
"id": "/api/greetings/cd",
"_id": "cd",
"name": "cd"
}
}
}
Entity/Greeting.php
Notice: ApiResource has totaly valid DataPersister and DataProvider defined.
<?php
// Entity/Greeting.php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Metadata\GraphQl\Query;
use ApiPlatform\Metadata\GraphQl\QueryCollection;
use App\State\DataProvider;
use App\State\DataPersister;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(
processor: DataPersister::class,
provider: DataProvider::class,
graphQlOperations: [
new Query(),
new QueryCollection(),
new DeleteMutation(
name: 'delete'
)
]
)]
class Greeting
{
private ?string $id = null;
public string $name = '';
public function __construct($id)
{
$this->id = $id;
$this->name = $id;
}
public function getId(): ?string
{
return $this->id;
}
}
State/DataProvider.php
<?php
// State/DataProvider.php
namespace App\State;
use App\Entity\Greeting;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use ApiPlatform\State\Pagination\TraversablePaginator;
use ApiPlatform\Metadata\CollectionOperationInterface;
final class DataProvider implements ProviderInterface
{
private $data;
function __construct()
{
$this->data = [
'ab' => new Greeting('ab'),
'cd' => new Greeting('cd'),
];
}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): iterable|Greeting|null
{
if ($operation instanceof CollectionOperationInterface) {
return new TraversablePaginator(new \ArrayObject($this->data), 0, count($this->data), count($this->data));
}
return $this->data[$uriVariables['id']] ?? null;
}
}
State/DataPersister.php
<?php
// State/DataPersister.php
namespace App\State;
use ApiPlatform\Metadata\DeleteOperationInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
final class DataPersister implements ProcessorInterface
{
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
return $data;
}
}
Here's the repository reproducing mentioned bug: https://github.com/danaki/api-platform-grapql-delete-mutation-bug-demo
Update: it seems it has nothing to do with custom Provider/Persister, but with serialization after DeleteMutation(). Obvious normalizationContext and denormalizationContext defining groups has no effect.
#[ApiResource(
processor: DataPersister::class,
provider: DataProvider::class,
normalizationContext: ['groups' => ['delete']],
denormalizationContext: ['groups' => ['delete']],
graphQlOperations: [
new Query(),
new QueryCollection(),
new DeleteMutation(
name: 'delete',
//serialize: false
)
]
)]
class Greeting
{
#[Groups(['delete'])]
private ?string $id = null;
#[Groups(['delete'])]
public string $name = '';
public function __construct($id)
{
$this->id = $id;
$this->name = $id;
}
public function getId(): ?string
{
return $this->id;
}
}
fails with ""Cannot return null for non-nullable field "Greeting.name"".
serialize: false (a commented line) helps to avoid error but also gives no output. Issue title updated.
don't you need to do something like https://github.com/api-platform/core/issues/6354 ?
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.