I am creating a web API using API Platform and entities are stored in a SQL database using Doctrine ORM.
Doctrine maps decimal type to PHP string. However, I'd like to expose decimal fields as JSON numbers while retaining the NUMERIC type in my SQL database. I am well aware that some precision can be lost using JSON numbers but I am OK to ignore it.
I tried using a getter and a setter for the decimal field(s):
#[ORM\Entity]
#[ApiResource]
class Product
{
#[ORM\Column(type: 'decimal', precision=10, scale=2)]
private string $price = '0';
public function getPrice(): float
{
return (float) $this->price;
}
public function setPrice(float|string $price): self
{
if (is_float($price)) {
$this->price = number_format($price, 2, '.', '');
}
else {
$this->price = $price;
}
return $this;
}
}
When serializing the entity to JSON/JSON-LD, the price field is correctly serialized to a number using getPrice():
{
"@id": "/api/products/1",
"@type": "Product",
"price": 65.3
}
However creating or updating a product with a number for the price value throws an error:
curl -X 'POST' \
"http://localhost:8000/api/products" \
-H 'Content-Type: application/ld+json' \
-d '{
"price": 120.6
}'
The type of the "price" attribute must be "string", "integer" given.
Edit: The setter is never called. The error is thrown by ApiPlatform\Core\Serializer\AbstractItemNormalizer from ValidateType() which is called by CreateAttributeValue().
Related: Doctrine GitHub issue