API Platform version(s) affected: ^4.2
Description
When using Symfony 7.1+ and API Platform 4.2+, properties defined as nullable arrays/collections of BackedEnums or Objects fail to be properly deserialized during POST or PATCH requests. Instead of being denormalized into instances of the Enum/Entity, the elements are left as raw strings.
This eventually results in database-level errors:
Doctrine\ORM\Mapping\ReflectionEnumProperty::getValue(): Argument #1 ($item) must be of type BackedEnum, string given
The bug is caused by API Platform's AbstractItemNormalizer::createAndValidateAttributeValue which checks if a property's type is a collection of objects using:
if (
($t instanceof CollectionType && $collectionValueType instanceof ObjectType)
|| ($t instanceof LegacyType && $t->isCollection() && null !== $collectionValueType && null !== $collectionValueType->getClassName())
)
When a property is nullable, Symfony's TypeInfo extracts a NullableType for its collection values. Since NullableType wraps the actual ObjectType/BackedEnumType but does not directly inherit from ObjectType, the condition $collectionValueType instanceof ObjectType evaluates to false. As a result, API Platform fails to delegate the collection items' denormalization to the Serializer.
How to reproduce
- Define a BackedEnum:
namespace App\Enum;
enum ContactNotificationsEnum: string
{
case Email = 'email';
case Sms = 'sms';
}
- Define a Doctrine entity with a nullable, array of BackedEnums column using Doctrine's
SIMPLE_ARRAY (or any typed array PHP property):
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use App\Enum\ContactNotificationsEnum;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\DBAL\Types\Types;
#[ORM\Entity]
#[ApiResource]
class CompanyContact
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
public ?int $id = null;
/**
* @var ContactNotificationsEnum[] $notificationType
*/
#[ORM\Column(type: Types::SIMPLE_ARRAY, enumType: ContactNotificationsEnum::class, nullable: true)]
public array $notificationType = [];
}
- Send a POST request to create a new
CompanyContact:
{
"notificationType": ["email"]
}
Results:
A HTTP 500 error is thrown by Doctrine:
Doctrine\ORM\Mapping\ReflectionEnumProperty::getValue(): Argument #1 ($item) must be of type BackedEnum, string given because the array elements remained raw strings.
Additional Context
I guess this behavior only started happening after the transition to Symfony's TypeInfo.
API Platform version(s) affected: ^4.2
Description
When using Symfony 7.1+ and API Platform 4.2+, properties defined as nullable arrays/collections of BackedEnums or Objects fail to be properly deserialized during POST or PATCH requests. Instead of being denormalized into instances of the Enum/Entity, the elements are left as raw strings.
This eventually results in database-level errors:
Doctrine\ORM\Mapping\ReflectionEnumProperty::getValue(): Argument #1 ($item) must be of type BackedEnum, string givenThe bug is caused by API Platform's
AbstractItemNormalizer::createAndValidateAttributeValuewhich checks if a property's type is a collection of objects using:When a property is nullable, Symfony's
TypeInfoextracts aNullableTypefor its collection values. SinceNullableTypewraps the actualObjectType/BackedEnumTypebut does not directly inherit fromObjectType, the condition$collectionValueType instanceof ObjectTypeevaluates tofalse. As a result, API Platform fails to delegate the collection items' denormalization to the Serializer.How to reproduce
SIMPLE_ARRAY(or any typed array PHP property):CompanyContact:{ "notificationType": ["email"] }Results:
A HTTP 500 error is thrown by Doctrine:
Doctrine\ORM\Mapping\ReflectionEnumProperty::getValue(): Argument #1 ($item) must be of type BackedEnum, string givenbecause the array elements remained raw strings.Additional Context
I guess this behavior only started happening after the transition to Symfony's
TypeInfo.